1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://www.hdfgroup.org/licenses.               *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 /*keep this declaration near the top of this file -RPM*/
15 static const char *FileHeader = "\n\
16 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\
17  * Copyright by The HDF Group.                                               *\n\
18  * Copyright by the Board of Trustees of the University of Illinois.         *\n\
19  * All rights reserved.                                                      *\n\
20  *                                                                           *\n\
21  * This file is part of HDF5.  The full HDF5 copyright notice, including     *\n\
22  * terms governing use, modification, and redistribution, is contained in    *\n\
23  * the COPYING file, which can be found at the root of the source code       *\n\
24  * distribution tree, or in https://www.hdfgroup.org/licenses.               *\n\
25  * If you do not have access to either file, you may request a copy from     *\n\
26  * help@hdfgroup.org.                                                        *\n\
27  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *";
28 /*
29  * Purpose:    This code was borrowed heavily from the `detect.c'
30  *        program in the AIO distribution from Lawrence
31  *        Livermore National Laboratory.
32  *
33  *        Detects machine byte order and floating point
34  *        format and generates a C source file (H5Tinit.c)
35  *        to describe those parameters.
36  *
37  * Assumptions: We have an ANSI compiler.  We're on a Unix like
38  *        system or configure has detected those Unix
39  *        features which aren't available.  We're not
40  *        running on a Vax or other machine with mixed
41  *        endianness.
42  *-------------------------------------------------------------------------
43  */
44 #undef NDEBUG
45 #include "H5private.h"
46 /* Do NOT use HDfprintf in this file as it is not linked with the library,
47  * which contains the H5system.c file in which the function is defined.
48  */
49 #include "H5Tpublic.h"
50 #include "H5Rpublic.h"
51 
52 /* Disable warning about cast increasing the alignment of the target type,
53  * that's _exactly_ what this code is probing.  -QAK
54  */
55 H5_GCC_DIAG_OFF("cast-align")
56 
57 #if defined(__has_attribute)
58 #if __has_attribute(no_sanitize_address)
59 #define HDF_NO_UBSAN __attribute__((no_sanitize_address))
60 #else
61 #define HDF_NO_UBSAN
62 #endif
63 #else
64 #define HDF_NO_UBSAN
65 #endif
66 
67 #define MAXDETECT 64
68 
69 /* The ALIGNMENT test code may generate the SIGBUS, SIGSEGV, or SIGILL signals.
70  * We use setjmp/longjmp in the signal handlers for recovery. But setjmp/longjmp
71  * do not necessary restore the signal blocking status while sigsetjmp/siglongjmp
72  * do. If sigsetjmp/siglongjmp are not supported, need to use sigprocmask to
73  * unblock the signal before doing longjmp.
74  */
75 /* Define H5SETJMP/H5LONGJMP depending on if sigsetjmp/siglongjmp are */
76 /* supported. */
77 #if defined(H5_HAVE_SIGSETJMP) && defined(H5_HAVE_SIGLONGJMP)
78 /* Always save blocked signals to be restored by siglongjmp. */
79 #define H5JMP_BUF           sigjmp_buf
80 #define H5SETJMP(buf)       HDsigsetjmp(buf, 1)
81 #define H5LONGJMP(buf, val) HDsiglongjmp(buf, val)
82 #define H5HAVE_SIGJMP       /* sigsetjmp/siglongjmp are supported. */
83 #elif defined(H5_HAVE_LONGJMP)
84 #define H5JMP_BUF           jmp_buf
85 #define H5SETJMP(buf)       HDsetjmp(buf)
86 #define H5LONGJMP(buf, val) HDlongjmp(buf, val)
87 #endif
88 
89 /* ALIGNMENT and signal-handling status codes */
90 #define STA_NoALIGNMENT     0x0001 /* No ALIGNMENT Test */
91 #define STA_NoHandlerVerify 0x0002 /* No signal handler Tests */
92 
93 /*
94  * This structure holds information about a type that
95  * was detected.
96  */
97 typedef struct detected_t {
98     const char *  varname;
99     unsigned int  size;             /* total byte size                  */
100     unsigned int  precision;        /* meaningful bits                  */
101     unsigned int  offset;           /* bit offset to meaningful bits    */
102     int           perm[32];         /* for detection of byte order      */
103     hbool_t       is_vax;           /* for vax (float & double) only    */
104     unsigned int  sign;             /* location of sign bit             */
105     unsigned int  mpos, msize, imp; /* information about mantissa       */
106     unsigned int  epos, esize;      /* information about exponent       */
107     unsigned long bias;             /* exponent bias for floating pt    */
108     unsigned int  align;            /* required byte alignment          */
109     unsigned int  comp_align;       /* alignment for structure          */
110 } detected_t;
111 
112 /* This structure holds structure alignment for pointers, vlen and reference
113  * types. */
114 typedef struct malign_t {
115     const char * name;
116     unsigned int comp_align; /* alignment for structure          */
117 } malign_t;
118 
119 FILE *rawoutstream = NULL;
120 
121 /* global variables types detection code */
122 H5_GCC_DIAG_OFF("larger-than=")
123 static detected_t d_g[MAXDETECT];
124 H5_GCC_DIAG_ON("larger-than=")
125 static malign_t     m_g[MAXDETECT];
126 static volatile int nd_g = 0, na_g = 0;
127 
128 static void         print_results(int nd, detected_t *d, int na, malign_t *m);
129 static void         iprint(detected_t *);
130 static int          byte_cmp(int, const void *, const void *, const unsigned char *);
131 static unsigned int bit_cmp(unsigned int, int *, void *, void *, const unsigned char *);
132 static void         fix_order(int, int, int *, const char **);
133 static unsigned int imp_bit(unsigned int, int *, void *, void *, const unsigned char *);
134 static unsigned int find_bias(unsigned int, unsigned int, int *, void *);
135 static void         precision(detected_t *);
136 static void         print_header(void);
137 static void         detect_C89_integers(void);
138 static void         detect_C89_floats(void);
139 static void         detect_C99_integers(void);
140 static void         detect_C99_floats(void);
141 static void         detect_C99_integers8(void);
142 static void         detect_C99_integers16(void);
143 static void         detect_C99_integers32(void);
144 static void         detect_C99_integers64(void);
145 static void         detect_alignments(void);
146 static unsigned int align_g[]                = {1, 2, 4, 8, 16};
147 static int          align_status_g           = 0; /* ALIGNMENT Signal Status */
148 static int          sigbus_handler_called_g  = 0; /* how many times called */
149 static int          sigsegv_handler_called_g = 0; /* how many times called */
150 static int          sigill_handler_called_g  = 0; /* how many times called */
151 static int          signal_handler_tested_g  = 0; /* how many times tested */
152 #if defined(H5SETJMP) && defined(H5_HAVE_SIGNAL)
153 static int verify_signal_handlers(int signum, void (*handler)(int));
154 #endif
155 #ifdef H5JMP_BUF
156 static H5JMP_BUF jbuf_g;
157 #endif
158 
159 /*-------------------------------------------------------------------------
160  * Function:    precision
161  *
162  * Purpose:     Determine the precision and offset.
163  *
164  * Return:      void
165  *-------------------------------------------------------------------------
166  */
167 static void
precision(detected_t * d)168 precision(detected_t *d)
169 {
170     unsigned int n;
171 
172     if (0 == d->msize) {
173         /*
174          * An integer.    The permutation can have negative values at the
175          * beginning or end which represent padding of bytes.  We must adjust
176          * the precision and offset accordingly.
177          */
178         if (d->perm[0] < 0) {
179             /*
180              * Lower addresses are padded.
181              */
182             for (n = 0; n < d->size && d->perm[n] < 0; n++)
183                 /*void*/;
184             d->precision = 8 * (d->size - n);
185             d->offset    = 0;
186         }
187         else if (d->perm[d->size - 1] < 0) {
188             /*
189              * Higher addresses are padded.
190              */
191             for (n = 0; n < d->size && d->perm[d->size - (n + 1)]; n++)
192                 /*void*/;
193             d->precision = 8 * (d->size - n);
194             d->offset    = 8 * n;
195         }
196         else {
197             /*
198              * No padding.
199              */
200             d->precision = 8 * d->size;
201             d->offset    = 0;
202         }
203     }
204     else {
205         /* A floating point */
206         d->offset    = MIN3(d->mpos, d->epos, d->sign);
207         d->precision = d->msize + d->esize + 1;
208     }
209 }
210 
211 /*-------------------------------------------------------------------------
212  * Function:    DETECT_I/DETECT_BYTE
213  *
214  * Purpose:     These macro takes a type like `int' and a base name like
215  *              `nati' and detects the byte order.  The VAR is used to
216  *              construct the names of the C variables defined.
217  *
218  *              DETECT_I is used for types that are larger than one byte,
219  *              DETECT_BYTE is used for types that are exactly one byte.
220  *
221  * Return:      void
222  *
223  *-------------------------------------------------------------------------
224  */
225 #define DETECT_I_BYTE_CORE(TYPE, VAR, INFO, DETECT_TYPE)                                                     \
226     {                                                                                                        \
227         DETECT_TYPE    _v;                                                                                   \
228         int            _i, _j;                                                                               \
229         unsigned char *_x;                                                                                   \
230                                                                                                              \
231         HDmemset(&INFO, 0, sizeof(INFO));                                                                    \
232         INFO.varname = #VAR;                                                                                 \
233         INFO.size    = sizeof(TYPE);                                                                         \
234                                                                                                              \
235         for (_i = sizeof(DETECT_TYPE), _v = 0; _i > 0; --_i)                                                 \
236             _v = (DETECT_TYPE)((DETECT_TYPE)(_v << 8) + (DETECT_TYPE)_i);                                    \
237                                                                                                              \
238         for (_i = 0, _x = (unsigned char *)&_v; _i < (signed)sizeof(DETECT_TYPE); _i++) {                    \
239             _j = (*_x++) - 1;                                                                                \
240             HDassert(_j < (signed)sizeof(DETECT_TYPE));                                                      \
241             INFO.perm[_i] = _j;                                                                              \
242         } /* end for */                                                                                      \
243                                                                                                              \
244         INFO.sign = ('U' != *(#VAR));                                                                        \
245         precision(&(INFO));                                                                                  \
246         ALIGNMENT(TYPE, INFO);                                                                               \
247         if (!HDstrcmp(INFO.varname, "SCHAR") || !HDstrcmp(INFO.varname, "SHORT") ||                          \
248             !HDstrcmp(INFO.varname, "INT") || !HDstrcmp(INFO.varname, "LONG") ||                             \
249             !HDstrcmp(INFO.varname, "LLONG")) {                                                              \
250             COMP_ALIGNMENT(TYPE, INFO.comp_align);                                                           \
251         }                                                                                                    \
252     }
253 
254 #define DETECT_BYTE(TYPE, VAR, INFO)                                                                         \
255     {                                                                                                        \
256         HDcompile_assert(sizeof(TYPE) == 1);                                                                 \
257                                                                                                              \
258         DETECT_I_BYTE_CORE(TYPE, VAR, INFO, int)                                                             \
259     }
260 
261 #define DETECT_I(TYPE, VAR, INFO)                                                                            \
262     {                                                                                                        \
263         HDcompile_assert(sizeof(TYPE) > 1);                                                                  \
264                                                                                                              \
265         DETECT_I_BYTE_CORE(TYPE, VAR, INFO, TYPE)                                                            \
266     }
267 
268 /*-------------------------------------------------------------------------
269  * Function:    DETECT_F
270  *
271  * Purpose:     This macro takes a floating point type like `double' and
272  *              a base name like `natd' and detects byte order, mantissa
273  *              location, exponent location, sign bit location, presence or
274  *              absence of implicit mantissa bit, and exponent bias and
275  *              initializes a detected_t structure with those properties.
276  *-------------------------------------------------------------------------
277  */
278 #define DETECT_F(TYPE, VAR, INFO)                                                                            \
279     {                                                                                                        \
280         TYPE          _v1, _v2, _v3;                                                                         \
281         unsigned char _buf1[sizeof(TYPE)], _buf3[sizeof(TYPE)];                                              \
282         unsigned char _pad_mask[sizeof(TYPE)];                                                               \
283         unsigned char _byte_mask;                                                                            \
284         int           _i, _j, _last = (-1);                                                                  \
285         const char *  _mesg;                                                                                 \
286                                                                                                              \
287         HDmemset(&INFO, 0, sizeof(INFO));                                                                    \
288         INFO.varname = #VAR;                                                                                 \
289         INFO.size    = sizeof(TYPE);                                                                         \
290                                                                                                              \
291         /* Initialize padding mask */                                                                        \
292         HDmemset(_pad_mask, 0, sizeof(_pad_mask));                                                           \
293                                                                                                              \
294         /* Padding bits.  Set a variable to 4.0, then flip each bit and see if                               \
295          * the modified variable is equal ("==") to the original.  Build a                                   \
296          * padding bitmask to indicate which bits in the type are padding (i.e.                              \
297          * have no effect on the value and should be ignored by subsequent                                   \
298          * steps).  This is necessary because padding bits can change arbitrarily                            \
299          * and interfere with detection of the various properties below unless we                            \
300          * know to ignore them. */                                                                           \
301         _v1 = (TYPE)4.0L;                                                                                    \
302         HDmemcpy(_buf1, (const void *)&_v1, sizeof(TYPE));                                                   \
303         for (_i = 0; _i < (int)sizeof(TYPE); _i++)                                                           \
304             for (_byte_mask = (unsigned char)1; _byte_mask; _byte_mask = (unsigned char)(_byte_mask << 1)) { \
305                 _buf1[_i] ^= _byte_mask;                                                                     \
306                 HDmemcpy((void *)&_v2, (const void *)_buf1, sizeof(TYPE));                                   \
307                 H5_GCC_DIAG_OFF("float-equal")                                                               \
308                 if (_v1 != _v2)                                                                              \
309                     _pad_mask[_i] |= _byte_mask;                                                             \
310                 H5_GCC_DIAG_ON("float-equal")                                                                \
311                 _buf1[_i] ^= _byte_mask;                                                                     \
312             } /* end for */                                                                                  \
313                                                                                                              \
314         /* Byte Order */                                                                                     \
315         for (_i = 0, _v1 = (TYPE)0.0L, _v2 = (TYPE)1.0L; _i < (int)sizeof(TYPE); _i++) {                     \
316             _v3 = _v1;                                                                                       \
317             _v1 += _v2;                                                                                      \
318             _v2 /= (TYPE)256.0L;                                                                             \
319             HDmemcpy(_buf1, (const void *)&_v1, sizeof(TYPE));                                               \
320             HDmemcpy(_buf3, (const void *)&_v3, sizeof(TYPE));                                               \
321             _j = byte_cmp(sizeof(TYPE), _buf3, _buf1, _pad_mask);                                            \
322             if (_j >= 0) {                                                                                   \
323                 INFO.perm[_i] = _j;                                                                          \
324                 _last         = _i;                                                                          \
325             }                                                                                                \
326         }                                                                                                    \
327         fix_order(sizeof(TYPE), _last, INFO.perm, (const char **)&_mesg);                                    \
328                                                                                                              \
329         if (!HDstrcmp(_mesg, "VAX"))                                                                         \
330             INFO.is_vax = TRUE;                                                                              \
331                                                                                                              \
332         /* Implicit mantissa bit */                                                                          \
333         _v1      = (TYPE)0.5L;                                                                               \
334         _v2      = (TYPE)1.0L;                                                                               \
335         INFO.imp = imp_bit(sizeof(TYPE), INFO.perm, &_v1, &_v2, _pad_mask);                                  \
336                                                                                                              \
337         /* Sign bit */                                                                                       \
338         _v1       = (TYPE)1.0L;                                                                              \
339         _v2       = (TYPE)-1.0L;                                                                             \
340         INFO.sign = bit_cmp(sizeof(TYPE), INFO.perm, &_v1, &_v2, _pad_mask);                                 \
341                                                                                                              \
342         /* Mantissa */                                                                                       \
343         INFO.mpos = 0;                                                                                       \
344                                                                                                              \
345         _v1        = (TYPE)1.0L;                                                                             \
346         _v2        = (TYPE)1.5L;                                                                             \
347         INFO.msize = bit_cmp(sizeof(TYPE), INFO.perm, &_v1, &_v2, _pad_mask);                                \
348         INFO.msize += 1 + (unsigned int)(INFO.imp ? 0 : 1) - INFO.mpos;                                      \
349                                                                                                              \
350         /* Exponent */                                                                                       \
351         INFO.epos = INFO.mpos + INFO.msize;                                                                  \
352                                                                                                              \
353         INFO.esize = INFO.sign - INFO.epos;                                                                  \
354                                                                                                              \
355         _v1       = (TYPE)1.0L;                                                                              \
356         INFO.bias = find_bias(INFO.epos, INFO.esize, INFO.perm, &_v1);                                       \
357         precision(&(INFO));                                                                                  \
358         ALIGNMENT(TYPE, INFO);                                                                               \
359         if (!HDstrcmp(INFO.varname, "FLOAT") || !HDstrcmp(INFO.varname, "DOUBLE") ||                         \
360             !HDstrcmp(INFO.varname, "LDOUBLE")) {                                                            \
361             COMP_ALIGNMENT(TYPE, INFO.comp_align);                                                           \
362         }                                                                                                    \
363     }
364 
365 /*-------------------------------------------------------------------------
366  * Function:    DETECT_M
367  *
368  * Purpose:     This macro takes only miscellaneous structures or pointer.
369  *              It constructs the names and decides the alignment in structure.
370  *
371  * Return:      void
372  *-------------------------------------------------------------------------
373  */
374 #define DETECT_M(TYPE, VAR, INFO)                                                                            \
375     {                                                                                                        \
376         INFO.name = #VAR;                                                                                    \
377         COMP_ALIGNMENT(TYPE, INFO.comp_align);                                                               \
378     }
379 
380 /* Detect alignment for C structure */
381 #define COMP_ALIGNMENT(TYPE, COMP_ALIGN)                                                                     \
382     {                                                                                                        \
383         struct {                                                                                             \
384             char c;                                                                                          \
385             TYPE x;                                                                                          \
386         } s;                                                                                                 \
387                                                                                                              \
388         COMP_ALIGN = (unsigned int)((char *)(&(s.x)) - (char *)(&s));                                        \
389     }
390 
391 #if defined(H5SETJMP) && defined(H5_HAVE_SIGNAL)
392 #define ALIGNMENT(TYPE, INFO)                                                                                \
393     {                                                                                                        \
394         char *volatile _buf    = NULL;                                                                       \
395         TYPE            _val   = 1, _val2;                                                                   \
396         volatile size_t _ano   = 0;                                                                          \
397         void (*_handler)(int)  = HDsignal(SIGBUS, sigbus_handler);                                           \
398         void (*_handler2)(int) = HDsignal(SIGSEGV, sigsegv_handler);                                         \
399         void (*_handler3)(int) = HDsignal(SIGILL, sigill_handler);                                           \
400                                                                                                              \
401         _buf = (char *)HDmalloc(sizeof(TYPE) + align_g[NELMTS(align_g) - 1]);                                \
402         if (H5SETJMP(jbuf_g))                                                                                \
403             _ano++;                                                                                          \
404         if (_ano < NELMTS(align_g)) {                                                                        \
405             *((TYPE *)(_buf + align_g[_ano])) = _val;  /*possible SIGBUS or SEGSEGV*/                        \
406             _val2 = *((TYPE *)(_buf + align_g[_ano])); /*possible SIGBUS or SEGSEGV*/                        \
407             /* Cray Check: This section helps detect alignment on Cray's */                                  \
408             /*              vector machines (like the SV1) which mask off */                                 \
409             /*              pointer values when pointing to non-word aligned */                              \
410             /*              locations with pointers that are supposed to be */                               \
411             /*              word aligned. -QAK */                                                            \
412             HDmemset(_buf, 0xff, sizeof(TYPE) + align_g[NELMTS(align_g) - 1]);                               \
413             /*How to handle VAX types?*/                                                                     \
414             if (INFO.perm[0]) /* Big-Endian */                                                               \
415                 HDmemcpy(_buf + align_g[_ano] + (INFO.size - ((INFO.offset + INFO.precision) / 8)),          \
416                          ((char *)&_val) + (INFO.size - ((INFO.offset + INFO.precision) / 8)),               \
417                          (size_t)(INFO.precision / 8));                                                      \
418             else /* Little-Endian */                                                                         \
419                 HDmemcpy(_buf + align_g[_ano] + (INFO.offset / 8), ((char *)&_val) + (INFO.offset / 8),      \
420                          (size_t)(INFO.precision / 8));                                                      \
421             _val2 = *((TYPE *)(_buf + align_g[_ano]));                                                       \
422             H5_GCC_DIAG_OFF("float-equal")                                                                   \
423             if (_val != _val2)                                                                               \
424                 H5LONGJMP(jbuf_g, 1);                                                                        \
425             H5_GCC_DIAG_ON("float-equal")                                                                    \
426             /* End Cray Check */                                                                             \
427             (INFO.align) = align_g[_ano];                                                                    \
428         }                                                                                                    \
429         else {                                                                                               \
430             (INFO.align) = 0;                                                                                \
431             fprintf(stderr, "unable to calculate alignment for %s\n", #TYPE);                                \
432         }                                                                                                    \
433         HDfree(_buf);                                                                                        \
434         HDsignal(SIGBUS, _handler);   /*restore original handler*/                                           \
435         HDsignal(SIGSEGV, _handler2); /*restore original handler*/                                           \
436         HDsignal(SIGILL, _handler3);  /*restore original handler*/                                           \
437     }
438 #else
439 #define ALIGNMENT(TYPE, INFO)                                                                                \
440     {                                                                                                        \
441         align_status_g |= STA_NoALIGNMENT;                                                                   \
442         (INFO.align) = 0;                                                                                    \
443     }
444 #endif
445 
446 #if defined(H5LONGJMP) && defined(H5_HAVE_SIGNAL)
447 
448 /*-------------------------------------------------------------------------
449  * Function:    sigsegv_handler
450  *
451  * Purpose:     Handler for SIGSEGV. We use signal() instead of sigaction()
452  *              because it's more portable to non-Posix systems. Although
453  *              it's not nearly as nice to work with, it does the job for
454  *              this simple stuff.
455  *
456  * Return:      Returns via H5LONGJMP to jbuf_g.
457  *-------------------------------------------------------------------------
458  */
459 static void
sigsegv_handler(int H5_ATTR_UNUSED signo)460 sigsegv_handler(int H5_ATTR_UNUSED signo)
461 {
462 #if !defined(H5HAVE_SIGJMP) && defined(H5_HAVE_SIGPROCMASK)
463     /* Use sigprocmask to unblock the signal if sigsetjmp/siglongjmp are not */
464     /* supported. */
465     sigset_t set;
466 
467     HDsigemptyset(&set);
468     HDsigaddset(&set, SIGSEGV);
469     HDsigprocmask(SIG_UNBLOCK, &set, NULL);
470 #endif
471 
472     sigsegv_handler_called_g++;
473     HDsignal(SIGSEGV, sigsegv_handler);
474     H5LONGJMP(jbuf_g, SIGSEGV);
475 }
476 #endif
477 
478 #if defined(H5LONGJMP) && defined(H5_HAVE_SIGNAL)
479 
480 /*-------------------------------------------------------------------------
481  * Function:    sigbus_handler
482  *
483  * Purpose:     Handler for SIGBUS. We use signal() instead of sigaction()
484  *              because it's more portable to non-Posix systems. Although
485  *              it's not nearly as nice to work with, it does the job for
486  *              this simple stuff.
487  *
488  * Return:      Returns via H5LONGJMP to jbuf_g.
489  *-------------------------------------------------------------------------
490  */
491 static void
sigbus_handler(int H5_ATTR_UNUSED signo)492 sigbus_handler(int H5_ATTR_UNUSED signo)
493 {
494 #if !defined(H5HAVE_SIGJMP) && defined(H5_HAVE_SIGPROCMASK)
495     /* Use sigprocmask to unblock the signal if sigsetjmp/siglongjmp are not */
496     /* supported. */
497     sigset_t set;
498 
499     HDsigemptyset(&set);
500     HDsigaddset(&set, SIGBUS);
501     HDsigprocmask(SIG_UNBLOCK, &set, NULL);
502 #endif
503 
504     sigbus_handler_called_g++;
505     HDsignal(SIGBUS, sigbus_handler);
506     H5LONGJMP(jbuf_g, SIGBUS);
507 }
508 #endif
509 
510 #if defined(H5LONGJMP) && defined(H5_HAVE_SIGNAL)
511 
512 /*-------------------------------------------------------------------------
513  * Function:    sigill_handler
514  *
515  * Purpose:     Handler for SIGILL. We use signal() instead of sigaction()
516  *              because it's more portable to non-Posix systems. Although
517  *              it's not nearly as nice to work with, it does the job for
518  *              this simple stuff.
519  *
520  * Return:      Returns via H5LONGJMP to jbuf_g.
521  *-------------------------------------------------------------------------
522  */
523 static void
sigill_handler(int H5_ATTR_UNUSED signo)524 sigill_handler(int H5_ATTR_UNUSED signo)
525 {
526 #if !defined(H5HAVE_SIGJMP) && defined(H5_HAVE_SIGPROCMASK)
527     /* Use sigprocmask to unblock the signal if sigsetjmp/siglongjmp are not */
528     /* supported. */
529     sigset_t set;
530 
531     HDsigemptyset(&set);
532     HDsigaddset(&set, SIGILL);
533     HDsigprocmask(SIG_UNBLOCK, &set, NULL);
534 #endif
535 
536     sigill_handler_called_g++;
537     HDsignal(SIGILL, sigill_handler);
538     H5LONGJMP(jbuf_g, SIGILL);
539 }
540 #endif
541 
542 /*-------------------------------------------------------------------------
543  * Function:    print_results
544  *
545  * Purpose:     Prints information about the detected data types.
546  *
547  * Return:      void
548  *-------------------------------------------------------------------------
549  */
550 static void
print_results(int nd,detected_t * d,int na,malign_t * misc_align)551 print_results(int nd, detected_t *d, int na, malign_t *misc_align)
552 {
553     int byte_order = 0; /*byte order of data types*/
554     int i, j;
555 
556     /* Include files */
557     fprintf(rawoutstream, "\
558 /****************/\n\
559 /* Module Setup */\n\
560 /****************/\n\
561 \n\
562 #include \"H5Tmodule.h\"          /* This source code file is part of the H5T module */\n\
563 \n\
564 \n\
565 /***********/\n\
566 /* Headers */\n\
567 /***********/\n\
568 #include \"H5private.h\"        /* Generic Functions            */\n\
569 #include \"H5Eprivate.h\"        /* Error handling              */\n\
570 #include \"H5FLprivate.h\"    /* Free Lists                */\n\
571 #include \"H5Iprivate.h\"        /* IDs                      */\n\
572 #include \"H5Tpkg.h\"        /* Datatypes                 */\n\
573 \n\
574 \n\
575 /****************/\n\
576 /* Local Macros */\n\
577 /****************/\n\
578 \n\
579 \n\
580 /******************/\n\
581 /* Local Typedefs */\n\
582 /******************/\n\
583 \n\
584 \n\
585 /********************/\n\
586 /* Package Typedefs */\n\
587 /********************/\n\
588 \n\
589 \n\
590 /********************/\n\
591 /* Local Prototypes */\n\
592 /********************/\n\
593 \n\
594 \n\
595 /********************/\n\
596 /* Public Variables */\n\
597 /********************/\n\
598 \n\
599 \n\
600 /*****************************/\n\
601 /* Library Private Variables */\n\
602 /*****************************/\n\
603 \n\
604 \n\
605 /*********************/\n\
606 /* Package Variables */\n\
607 /*********************/\n\
608 \n\
609 \n");
610     fprintf(rawoutstream, "\n\
611 /*******************/\n\
612 /* Local Variables */\n\
613 /*******************/\n\
614 \n");
615 
616     /* The interface initialization function */
617     fprintf(rawoutstream, "\n\
618 \n\
619 /*-------------------------------------------------------------------------\n\
620  * Function:    H5T__init_native\n\
621  *\n\
622  * Purpose:    Initialize pre-defined native datatypes from code generated\n\
623  *              during the library configuration by H5detect.\n\
624  *\n\
625  * Return:    Success:    non-negative\n\
626  *        Failure:    negative\n\
627  *\n\
628  * Programmer:    Robb Matzke\n\
629  *              Wednesday, December 16, 1998\n\
630  *\n\
631  *-------------------------------------------------------------------------\n\
632  */\n\
633 herr_t\n\
634 H5T__init_native(void)\n\
635 {\n\
636     H5T_t    *dt = NULL;\n\
637     herr_t    ret_value = SUCCEED;\n\
638 \n\
639     FUNC_ENTER_PACKAGE\n");
640 
641     for (i = 0; i < nd; i++) {
642         /* The native endianness of this machine */
643         /* The INFO.perm now contains `-1' for bytes that aren't used and
644          * are always zero.  This happens on the Cray for `short' where
645          * sizeof(short) is 8, but only the low-order 4 bytes are ever used.
646          */
647         if (d[i].is_vax) /* the type is a VAX floating number */
648             byte_order = -1;
649         else {
650             for (j = 0; j < 32; j++) {
651                 /*Find the 1st containing valid data*/
652                 if (d[i].perm[j] > -1) {
653                     byte_order = d[i].perm[j];
654                     break;
655                 }
656             }
657         }
658 
659         /* Print a comment to describe this section of definitions. */
660         fprintf(rawoutstream, "\n   /*\n");
661         iprint(d + i);
662         fprintf(rawoutstream, "    */\n");
663 
664         /* The part common to fixed and floating types */
665         fprintf(rawoutstream, "\
666     if(NULL == (dt = H5T__alloc()))\n\
667         HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, FAIL, \"datatype allocation failed\")\n\
668     dt->shared->state = H5T_STATE_IMMUTABLE;\n\
669     dt->shared->type = H5T_%s;\n\
670     dt->shared->size = %d;\n",
671                 d[i].msize ? "FLOAT" : "INTEGER", /*class            */
672                 d[i].size);                       /*size            */
673 
674         if (byte_order == -1)
675             fprintf(rawoutstream, "\
676     dt->shared->u.atomic.order = H5T_ORDER_VAX;\n");
677         else if (byte_order == 0)
678             fprintf(rawoutstream, "\
679     dt->shared->u.atomic.order = H5T_ORDER_LE;\n");
680         else
681             fprintf(rawoutstream, "\
682     dt->shared->u.atomic.order = H5T_ORDER_BE;\n");
683 
684         fprintf(rawoutstream, "\
685     dt->shared->u.atomic.offset = %d;\n\
686     dt->shared->u.atomic.prec = %d;\n\
687     dt->shared->u.atomic.lsb_pad = H5T_PAD_ZERO;\n\
688     dt->shared->u.atomic.msb_pad = H5T_PAD_ZERO;\n",
689                 d[i].offset,                            /*offset        */
690                 d[i].precision);                        /*precision        */
691         /*HDassert((d[i].perm[0]>0)==(byte_order>0));*/ /* Double-check that byte-order doesn't change */
692 
693         if (0 == d[i].msize) {
694             /* The part unique to fixed point types */
695             fprintf(rawoutstream, "\
696     dt->shared->u.atomic.u.i.sign = H5T_SGN_%s;\n",
697                     d[i].sign ? "2" : "NONE");
698         }
699         else {
700             /* The part unique to floating point types */
701             fprintf(rawoutstream, "\
702     dt->shared->u.atomic.u.f.sign = %d;\n\
703     dt->shared->u.atomic.u.f.epos = %d;\n\
704     dt->shared->u.atomic.u.f.esize = %d;\n\
705     dt->shared->u.atomic.u.f.ebias = 0x%08lx;\n\
706     dt->shared->u.atomic.u.f.mpos = %d;\n\
707     dt->shared->u.atomic.u.f.msize = %d;\n\
708     dt->shared->u.atomic.u.f.norm = H5T_NORM_%s;\n\
709     dt->shared->u.atomic.u.f.pad = H5T_PAD_ZERO;\n",
710                     d[i].sign,                      /*sign location */
711                     d[i].epos,                      /*exponent loc    */
712                     d[i].esize,                     /*exponent size */
713                     (unsigned long)(d[i].bias),     /*exponent bias */
714                     d[i].mpos,                      /*mantissa loc    */
715                     d[i].msize,                     /*mantissa size */
716                     d[i].imp ? "IMPLIED" : "NONE"); /*normalization */
717         }
718 
719         /* Atomize the type */
720         fprintf(rawoutstream, "\
721     if((H5T_NATIVE_%s_g = H5I_register(H5I_DATATYPE, dt, FALSE)) < 0)\n\
722         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, \"can't register ID for built-in datatype\")\n",
723                 d[i].varname);
724         fprintf(rawoutstream, "    H5T_NATIVE_%s_ALIGN_g = %lu;\n", d[i].varname,
725                 (unsigned long)(d[i].align));
726 
727         /* Variables for alignment of compound datatype */
728         if (!HDstrcmp(d[i].varname, "SCHAR") || !HDstrcmp(d[i].varname, "SHORT") ||
729             !HDstrcmp(d[i].varname, "INT") || !HDstrcmp(d[i].varname, "LONG") ||
730             !HDstrcmp(d[i].varname, "LLONG") || !HDstrcmp(d[i].varname, "FLOAT") ||
731             !HDstrcmp(d[i].varname, "DOUBLE") || !HDstrcmp(d[i].varname, "LDOUBLE")) {
732             fprintf(rawoutstream, "    H5T_NATIVE_%s_COMP_ALIGN_g = %lu;\n", d[i].varname,
733                     (unsigned long)(d[i].comp_align));
734         }
735     }
736 
737     /* Consider VAX a little-endian machine */
738     if (byte_order == 0 || byte_order == -1) {
739         fprintf(rawoutstream, "\n\
740     /* Set the native order for this machine */\n\
741     H5T_native_order_g = H5T_ORDER_%s;\n",
742                 "LE");
743     }
744     else {
745         fprintf(rawoutstream, "\n\
746     /* Set the native order for this machine */\n\
747     H5T_native_order_g = H5T_ORDER_%s;\n",
748                 "BE");
749     }
750 
751     /* Structure alignment for pointers, vlen and reference types */
752     fprintf(rawoutstream, "\n    /* Structure alignment for pointers, vlen and reference types */\n");
753     for (j = 0; j < na; j++)
754         fprintf(rawoutstream, "    H5T_%s_COMP_ALIGN_g = %lu;\n", misc_align[j].name,
755                 (unsigned long)(misc_align[j].comp_align));
756 
757     fprintf(rawoutstream, "\
758 \n\
759 done:\n\
760     if(ret_value < 0) {\n\
761         if(dt != NULL) {\n\
762             dt->shared = H5FL_FREE(H5T_shared_t, dt->shared);\n\
763             dt = H5FL_FREE(H5T_t, dt);\n\
764         } /* end if */\n\
765     } /* end if */\n\
766 \n\
767     FUNC_LEAVE_NOAPI(ret_value);\n} /* end H5T__init_native() */\n");
768 
769     /* Print the ALIGNMENT and signal-handling status as comments */
770     fprintf(rawoutstream, "\n"
771                           "/****************************************/\n"
772                           "/* ALIGNMENT and signal-handling status */\n"
773                           "/****************************************/\n");
774     if (align_status_g & STA_NoALIGNMENT)
775         fprintf(rawoutstream, "/* ALIGNAMENT test is not available */\n");
776     if (align_status_g & STA_NoHandlerVerify)
777         fprintf(rawoutstream, "/* Signal handlers verify test is not available */\n");
778         /* The following is available in H5pubconf.h. Printing them here for */
779         /* convenience. */
780 #ifdef H5_HAVE_SIGNAL
781     fprintf(rawoutstream, "/* Signal() support: yes */\n");
782 #else
783     fprintf(rawoutstream, "/* Signal() support: no */\n");
784 #endif
785 #ifdef H5_HAVE_SETJMP
786     fprintf(rawoutstream, "/* setjmp() support: yes */\n");
787 #else
788     fprintf(rawoutstream, "/* setjmp() support: no */\n");
789 #endif
790 #ifdef H5_HAVE_LONGJMP
791     fprintf(rawoutstream, "/* longjmp() support: yes */\n");
792 #else
793     fprintf(rawoutstream, "/* longjmp() support: no */\n");
794 #endif
795 #ifdef H5_HAVE_SIGSETJMP
796     fprintf(rawoutstream, "/* sigsetjmp() support: yes */\n");
797 #else
798     fprintf(rawoutstream, "/* sigsetjmp() support: no */\n");
799 #endif
800 #ifdef H5_HAVE_SIGLONGJMP
801     fprintf(rawoutstream, "/* siglongjmp() support: yes */\n");
802 #else
803     fprintf(rawoutstream, "/* siglongjmp() support: no */\n");
804 #endif
805 #ifdef H5_HAVE_SIGPROCMASK
806     fprintf(rawoutstream, "/* sigprocmask() support: yes */\n");
807 #else
808     fprintf(rawoutstream, "/* sigprocmask() support: no */\n");
809 #endif
810 
811     /* Print the statics of signal handlers called for debugging */
812     fprintf(rawoutstream, "\n"
813                           "/******************************/\n"
814                           "/* signal handlers statistics */\n"
815                           "/******************************/\n");
816     fprintf(rawoutstream, "/* signal_handlers tested: %d times */\n", signal_handler_tested_g);
817     fprintf(rawoutstream, "/* sigbus_handler called: %d times */\n", sigbus_handler_called_g);
818     fprintf(rawoutstream, "/* sigsegv_handler called: %d times */\n", sigsegv_handler_called_g);
819     fprintf(rawoutstream, "/* sigill_handler called: %d times */\n", sigill_handler_called_g);
820 } /* end print_results() */
821 
822 /*-------------------------------------------------------------------------
823  * Function:    iprint
824  *
825  * Purpose:     Prints information about the fields of a floating point format.
826  *
827  * Return:      void
828 
829  *-------------------------------------------------------------------------
830  */
831 static void
iprint(detected_t * d)832 iprint(detected_t *d)
833 {
834     unsigned int pass;
835 
836     for (pass = (d->size - 1) / 4;; --pass) {
837         unsigned int i, k;
838         /*
839          * Print the byte ordering above the bit fields.
840          */
841         fprintf(rawoutstream, "    * ");
842         for (i = MIN(pass * 4 + 3, d->size - 1); i >= pass * 4; --i) {
843             fprintf(rawoutstream, "%4d", d->perm[i]);
844             if (i > pass * 4)
845                 HDfputs("     ", stdout);
846             if (!i)
847                 break;
848         }
849 
850         /*
851          * Print the bit fields
852          */
853         fprintf(rawoutstream, "\n    * ");
854         for (i = MIN(pass * 4 + 3, d->size - 1), k = MIN(pass * 32 + 31, 8 * d->size - 1); i >= pass * 4;
855              --i) {
856             unsigned int j;
857 
858             for (j = 8; j > 0; --j) {
859                 if (k == d->sign && d->msize) {
860                     HDfputc('S', rawoutstream);
861                 }
862                 else if (k >= d->epos && k < d->epos + d->esize) {
863                     HDfputc('E', rawoutstream);
864                 }
865                 else if (k >= d->mpos && k < d->mpos + d->msize) {
866                     HDfputc('M', rawoutstream);
867                 }
868                 else if (d->msize) {
869                     HDfputc('?', rawoutstream); /*unknown floating point bit */
870                 }
871                 else if (d->sign) {
872                     HDfputc('I', rawoutstream);
873                 }
874                 else {
875                     HDfputc('U', rawoutstream);
876                 }
877                 --k;
878             }
879             if (i > pass * 4)
880                 HDfputc(' ', rawoutstream);
881             if (!i)
882                 break;
883         }
884         HDfputc('\n', rawoutstream);
885         if (!pass)
886             break;
887     }
888 
889     /*
890      * Is there an implicit bit in the mantissa.
891      */
892     if (d->msize) {
893         fprintf(rawoutstream, "    * Implicit bit? %s\n", d->imp ? "yes" : "no");
894     }
895 
896     /*
897      * Alignment
898      */
899     if (0 == d->align) {
900         fprintf(rawoutstream, "    * Alignment: NOT CALCULATED\n");
901     }
902     else if (1 == d->align) {
903         fprintf(rawoutstream, "    * Alignment: none\n");
904     }
905     else {
906         fprintf(rawoutstream, "    * Alignment: %lu\n", (unsigned long)(d->align));
907     }
908 }
909 
910 /*-------------------------------------------------------------------------
911  * Function:    byte_cmp
912  *
913  * Purpose:     Compares two chunks of memory A and B and returns the
914  *              byte index into those arrays of the first byte that
915  *              differs between A and B.  Ignores differences where the
916  *              corresponding bit in pad_mask is set to 0.
917  *
918  * Return:      Success:    Index of differing byte.
919  *              Failure:    -1 if all bytes are the same.
920  *-------------------------------------------------------------------------
921  */
922 static int
byte_cmp(int n,const void * _a,const void * _b,const unsigned char * pad_mask)923 byte_cmp(int n, const void *_a, const void *_b, const unsigned char *pad_mask)
924 {
925     int                  i;
926     const unsigned char *a = (const unsigned char *)_a;
927     const unsigned char *b = (const unsigned char *)_b;
928 
929     for (i = 0; i < n; i++)
930         if ((a[i] & pad_mask[i]) != (b[i] & pad_mask[i]))
931             return i;
932 
933     return -1;
934 }
935 
936 /*-------------------------------------------------------------------------
937  * Function:    bit_cmp
938  *
939  * Purpose:     Compares two bit vectors and returns the index for the
940  *              first bit that differs between the two vectors.     The
941  *              size of the vector is NBYTES.  PERM is a mapping from
942  *              actual order to little endian.  Ignores differences where
943  *              the corresponding bit in pad_mask is set to 0.
944  *
945  * Return:      Index of first differing bit.
946  *
947  *-------------------------------------------------------------------------
948  */
949 static unsigned int
bit_cmp(unsigned int nbytes,int * perm,void * _a,void * _b,const unsigned char * pad_mask)950 bit_cmp(unsigned int nbytes, int *perm, void *_a, void *_b, const unsigned char *pad_mask)
951 {
952     unsigned int   i;
953     unsigned char *a = (unsigned char *)_a;
954     unsigned char *b = (unsigned char *)_b;
955     unsigned char  aa, bb;
956 
957     for (i = 0; i < nbytes; i++) {
958         HDassert(perm[i] < (int)nbytes);
959         if ((aa = (unsigned char)(a[perm[i]] & pad_mask[perm[i]])) !=
960             (bb = (unsigned char)(b[perm[i]] & pad_mask[perm[i]]))) {
961             unsigned int j;
962 
963             for (j = 0; j < 8; j++, aa >>= 1, bb >>= 1) {
964                 if ((aa & 1) != (bb & 1))
965                     return i * 8 + j;
966             }
967             fprintf(stderr, "INTERNAL ERROR");
968             HDabort();
969         }
970     }
971     fprintf(stderr, "INTERNAL ERROR");
972     HDabort();
973     return 0;
974 }
975 
976 /*-------------------------------------------------------------------------
977  * Function:    fix_order
978  *
979  * Purpose:      Given an array PERM with elements FIRST through LAST
980  *              initialized with zero origin byte numbers, this function
981  *              creates a permutation vector that maps the actual order
982  *              of a floating point number to little-endian.
983  *
984  *              This function assumes that the mantissa byte ordering
985  *              implies the total ordering.
986  *
987  * Return:      void
988  *-------------------------------------------------------------------------
989  */
990 static void
fix_order(int n,int last,int * perm,const char ** mesg)991 fix_order(int n, int last, int *perm, const char **mesg)
992 {
993     int i;
994 
995     if (last > 1) {
996         /*
997          * We have at least three points to consider.
998          */
999         if (perm[last] < perm[last - 1] && perm[last - 1] < perm[last - 2]) {
1000             /*
1001              * Little endian.
1002              */
1003             if (mesg)
1004                 *mesg = "Little-endian";
1005             for (i = 0; i < n; i++)
1006                 perm[i] = i;
1007         }
1008         else if (perm[last] > perm[last - 1] && perm[last - 1] > perm[last - 2]) {
1009             /*
1010              * Big endian.
1011              */
1012             if (mesg)
1013                 *mesg = "Big-endian";
1014             for (i = 0; i < n; i++)
1015                 perm[i] = (n - 1) - i;
1016         }
1017         else {
1018             /*
1019              * Bi-endian machines like VAX.
1020              * (NOTE: This is not an actual determination of the VAX-endianness.
1021              *          It could have some other endianness and fall into this
1022              *          case - JKM & QAK)
1023              */
1024             HDassert(0 == n % 2);
1025             if (mesg)
1026                 *mesg = "VAX";
1027             for (i = 0; i < n; i += 2) {
1028                 perm[i]     = (n - 2) - i;
1029                 perm[i + 1] = (n - 1) - i;
1030             }
1031         }
1032     }
1033     else {
1034         fprintf(stderr, "Failed to detect byte order of %d-byte floating point.\n", n);
1035         HDexit(1);
1036     }
1037 }
1038 
1039 /*-------------------------------------------------------------------------
1040  * Function:    imp_bit
1041  *
1042  * Purpose:     Looks for an implicit bit in the mantissa.  The value
1043  *              of _A should be 1.0 and the value of _B should be 0.5.
1044  *              Some floating-point formats discard the most significant
1045  *              bit of the mantissa after normalizing since it will always
1046  *              be a one (except for 0.0).  If this is true for the native
1047  *              floating point values stored in _A and _B then the function
1048  *              returns non-zero.
1049  *
1050  *              This function assumes that the exponent occupies higher
1051  *              order bits than the mantissa and that the most significant
1052  *              bit of the mantissa is next to the least significant bit
1053  *              of the exponent.
1054  *
1055  *
1056  * Return:      Success:    Non-zero if the most significant bit
1057  *                          of the mantissa is discarded (ie, the
1058  *                          mantissa has an implicit `one' as the
1059  *                          most significant bit).    Otherwise,
1060  *                          returns zero.
1061  *
1062  *              Failure:    1
1063  *
1064  *-------------------------------------------------------------------------
1065  */
1066 static unsigned int
imp_bit(unsigned int n,int * perm,void * _a,void * _b,const unsigned char * pad_mask)1067 imp_bit(unsigned int n, int *perm, void *_a, void *_b, const unsigned char *pad_mask)
1068 {
1069     unsigned char *a = (unsigned char *)_a;
1070     unsigned char *b = (unsigned char *)_b;
1071     unsigned int   changed, major, minor;
1072     unsigned int   msmb; /* most significant mantissa bit */
1073 
1074     /*
1075      * Look for the least significant bit that has changed between
1076      * A and B.  This is the least significant bit of the exponent.
1077      */
1078     changed = bit_cmp(n, perm, a, b, pad_mask);
1079 
1080     /*
1081      * The bit to the right (less significant) of the changed bit should
1082      * be the most significant bit of the mantissa.  If it is non-zero
1083      * then the format does not remove the leading `1' of the mantissa.
1084      */
1085     msmb  = changed - 1;
1086     major = msmb / 8;
1087     minor = msmb % 8;
1088 
1089     return (a[perm[major]] >> minor) & 0x01 ? 0 : 1;
1090 }
1091 
1092 /*-------------------------------------------------------------------------
1093  * Function:  find_bias
1094  *
1095  * Purpose:   Determines the bias of the exponent.  This function should
1096  *            be called with _A having a value of `1'.
1097  *
1098  * Return:    The exponent bias.
1099  *
1100  *-------------------------------------------------------------------------
1101  */
1102 H5_ATTR_PURE static unsigned int
find_bias(unsigned int epos,unsigned int esize,int * perm,void * _a)1103 find_bias(unsigned int epos, unsigned int esize, int *perm, void *_a)
1104 {
1105     unsigned char *a = (unsigned char *)_a;
1106     unsigned char  mask;
1107     unsigned int   b, shift = 0, nbits, bias = 0;
1108 
1109     while (esize > 0) {
1110         nbits = MIN(esize, (8 - epos % 8));
1111         mask  = (unsigned char)((1 << nbits) - 1);
1112         b     = (unsigned int)(a[perm[epos / 8]] >> (epos % 8)) & mask;
1113         bias |= b << shift;
1114 
1115         shift += nbits;
1116         esize -= nbits;
1117         epos += nbits;
1118     }
1119     return bias;
1120 }
1121 
1122 /*-------------------------------------------------------------------------
1123  * Function:    print_header
1124  *
1125  * Purpose:     Prints the C file header for the generated file.
1126  *
1127  * Return:      void
1128  *-------------------------------------------------------------------------
1129  */
1130 static void
print_header(void)1131 print_header(void)
1132 {
1133 
1134     time_t      now = HDtime(NULL);
1135     struct tm * tm  = HDlocaltime(&now);
1136     char        real_name[30];
1137     char        host_name[256];
1138     int         i;
1139     const char *s;
1140 #ifdef H5_HAVE_GETPWUID
1141     struct passwd *pwd = NULL;
1142 #else
1143     int pwd      = 1;
1144 #endif
1145     static const char *month_name[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
1146                                        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
1147     static const char *purpose      = "\
1148 This machine-generated source code contains\n\
1149 information about the various integer and\n\
1150 floating point numeric formats found on this\n\
1151 architecture.  The parameters below should be\n\
1152 checked carefully and errors reported to the\n\
1153 HDF5 maintainer.\n\
1154 \n\
1155 Each of the numeric formats listed below are\n\
1156 printed from most significant bit to least\n\
1157 significant bit even though the actual bytes\n\
1158 might be stored in a different order in\n\
1159 memory.     The integers above each binary byte\n\
1160 indicate the relative order of the bytes in\n\
1161 memory; little-endian machines have\n\
1162 decreasing numbers while big-endian machines\n\
1163 have increasing numbers.\n\
1164 \n\
1165 The fields of the numbers are printed as\n\
1166 letters with `S' for the mantissa sign bit,\n\
1167 `M' for the mantissa magnitude, and `E' for\n\
1168 the exponent.  The exponent has an associated\n\
1169 bias which can be subtracted to find the\n\
1170 true exponent.    The radix point is assumed\n\
1171 to be before the first `M' bit.     Any bit\n\
1172 of a floating-point value not falling into one\n\
1173 of these categories is printed as a question\n\
1174 mark.  Bits of integer types are printed as\n\
1175 `I' for 2's complement and `U' for magnitude.\n\
1176 \n\
1177 If the most significant bit of the normalized\n\
1178 mantissa (always a `1' except for `0.0') is\n\
1179 not stored then an `implicit=yes' appears\n\
1180 under the field description.  In this case,\n\
1181 the radix point is still assumed to be\n\
1182 before the first `M' but after the implicit\n\
1183 bit.\n";
1184 
1185     /*
1186      * The real name is the first item from the passwd gecos field.
1187      */
1188 #ifdef H5_HAVE_GETPWUID
1189     {
1190         size_t n;
1191         char * comma;
1192         if ((pwd = HDgetpwuid(HDgetuid()))) {
1193             if ((comma = HDstrchr(pwd->pw_gecos, ','))) {
1194                 n = MIN(sizeof(real_name) - 1, (unsigned)(comma - pwd->pw_gecos));
1195                 HDstrncpy(real_name, pwd->pw_gecos, n);
1196                 real_name[n] = '\0';
1197             }
1198             else {
1199                 HDstrncpy(real_name, pwd->pw_gecos, sizeof(real_name));
1200                 real_name[sizeof(real_name) - 1] = '\0';
1201             }
1202         }
1203         else
1204             real_name[0] = '\0';
1205     }
1206 #else
1207     real_name[0] = '\0';
1208 #endif
1209 
1210     /*
1211      * The FQDM of this host or the empty string.
1212      */
1213 #ifdef H5_HAVE_GETHOSTNAME
1214     if (HDgethostname(host_name, sizeof(host_name)) < 0) {
1215         host_name[0] = '\0';
1216     }
1217 #else
1218     host_name[0] = '\0';
1219 #endif
1220 
1221     /*
1222      * The file header: warning, copyright notice, build information.
1223      */
1224     fprintf(rawoutstream, "/* Generated automatically by H5detect -- do not edit */\n\n\n");
1225     HDfputs(FileHeader, rawoutstream); /*the copyright notice--see top of this file */
1226 
1227     fprintf(rawoutstream, " *\n * Created:\t\t%s %2d, %4d\n", month_name[tm->tm_mon], tm->tm_mday,
1228             1900 + tm->tm_year);
1229     if (pwd || real_name[0] || host_name[0]) {
1230         fprintf(rawoutstream, " *\t\t\t");
1231         if (real_name[0])
1232             fprintf(rawoutstream, "%s <", real_name);
1233 #ifdef H5_HAVE_GETPWUID
1234         if (pwd)
1235             HDfputs(pwd->pw_name, rawoutstream);
1236 #endif
1237         if (host_name[0])
1238             fprintf(rawoutstream, "@%s", host_name);
1239         if (real_name[0])
1240             fprintf(rawoutstream, ">");
1241         HDfputc('\n', rawoutstream);
1242     }
1243     fprintf(rawoutstream, " *\n * Purpose:\t\t");
1244     for (s = purpose; *s; s++) {
1245         HDfputc(*s, rawoutstream);
1246         if ('\n' == *s && s[1])
1247             fprintf(rawoutstream, " *\t\t\t");
1248     }
1249 
1250     fprintf(rawoutstream, " *\n * Modifications:\n *\n");
1251     fprintf(rawoutstream, " *\tDO NOT MAKE MODIFICATIONS TO THIS FILE!\n");
1252     fprintf(rawoutstream, " *\tIt was generated by code in `H5detect.c'.\n");
1253 
1254     fprintf(rawoutstream, " *\n *");
1255     for (i = 0; i < 73; i++)
1256         HDfputc('-', rawoutstream);
1257     fprintf(rawoutstream, "\n */\n\n");
1258 }
1259 
1260 /*-------------------------------------------------------------------------
1261  * Function:    detect_C89_integers
1262  *
1263  * Purpose:     Detect C89 integer types
1264  *
1265  * Return:      void
1266  *-------------------------------------------------------------------------
1267  */
1268 static void HDF_NO_UBSAN
detect_C89_integers(void)1269 detect_C89_integers(void)
1270 {
1271     DETECT_BYTE(signed char, SCHAR, d_g[nd_g]);
1272     nd_g++;
1273     DETECT_BYTE(unsigned char, UCHAR, d_g[nd_g]);
1274     nd_g++;
1275     DETECT_I(short, SHORT, d_g[nd_g]);
1276     nd_g++;
1277     DETECT_I(unsigned short, USHORT, d_g[nd_g]);
1278     nd_g++;
1279     DETECT_I(int, INT, d_g[nd_g]);
1280     nd_g++;
1281     DETECT_I(unsigned int, UINT, d_g[nd_g]);
1282     nd_g++;
1283     DETECT_I(long, LONG, d_g[nd_g]);
1284     nd_g++;
1285     DETECT_I(unsigned long, ULONG, d_g[nd_g]);
1286     nd_g++;
1287 }
1288 
1289 /*-------------------------------------------------------------------------
1290  * Function:    detect_C89_floats
1291  *
1292  * Purpose:     Detect C89 floating point types
1293  *
1294  * Return:      void
1295  *-------------------------------------------------------------------------
1296  */
1297 static void HDF_NO_UBSAN
detect_C89_floats(void)1298 detect_C89_floats(void)
1299 {
1300     DETECT_F(float, FLOAT, d_g[nd_g]);
1301     nd_g++;
1302     DETECT_F(double, DOUBLE, d_g[nd_g]);
1303     nd_g++;
1304 }
1305 
1306 /*-------------------------------------------------------------------------
1307  * Function:    detect_C99_integers8
1308  *
1309  * Purpose:     Detect C99 8 bit integer types
1310  *
1311  * Return:      void
1312  *-------------------------------------------------------------------------
1313  */
1314 static void HDF_NO_UBSAN
detect_C99_integers8(void)1315 detect_C99_integers8(void)
1316 {
1317 #if H5_SIZEOF_INT8_T > 0
1318 #if H5_SIZEOF_INT8_T == 1
1319     DETECT_BYTE(int8_t, INT8, d_g[nd_g]);
1320     nd_g++;
1321 #else
1322     DETECT_I(int8_t, INT8, d_g[nd_g]);
1323     nd_g++;
1324 #endif
1325 #endif
1326 #if H5_SIZEOF_UINT8_T > 0
1327 #if H5_SIZEOF_UINT8_T == 1
1328     DETECT_BYTE(uint8_t, UINT8, d_g[nd_g]);
1329     nd_g++;
1330 #else
1331     DETECT_I(uint8_t, UINT8, d_g[nd_g]);
1332     nd_g++;
1333 #endif
1334 #endif
1335 #if H5_SIZEOF_INT_LEAST8_T > 0
1336 #if H5_SIZEOF_INT_LEAST8_T == 1
1337     DETECT_BYTE(int_least8_t, INT_LEAST8, d_g[nd_g]);
1338     nd_g++;
1339 #else
1340     DETECT_I(int_least8_t, INT_LEAST8, d_g[nd_g]);
1341     nd_g++;
1342 #endif
1343 #endif
1344 #if H5_SIZEOF_UINT_LEAST8_T > 0
1345 #if H5_SIZEOF_UINT_LEAST8_T == 1
1346     DETECT_BYTE(uint_least8_t, UINT_LEAST8, d_g[nd_g]);
1347     nd_g++;
1348 #else
1349     DETECT_I(uint_least8_t, UINT_LEAST8, d_g[nd_g]);
1350     nd_g++;
1351 #endif
1352 #endif
1353 #if H5_SIZEOF_INT_FAST8_T > 0
1354 #if H5_SIZEOF_INT_FAST8_T == 1
1355     DETECT_BYTE(int_fast8_t, INT_FAST8, d_g[nd_g]);
1356     nd_g++;
1357 #else
1358     DETECT_I(int_fast8_t, INT_FAST8, d_g[nd_g]);
1359     nd_g++;
1360 #endif
1361 #endif
1362 #if H5_SIZEOF_UINT_FAST8_T > 0
1363 #if H5_SIZEOF_UINT_FAST8_T == 1
1364     DETECT_BYTE(uint_fast8_t, UINT_FAST8, d_g[nd_g]);
1365     nd_g++;
1366 #else
1367     DETECT_I(uint_fast8_t, UINT_FAST8, d_g[nd_g]);
1368     nd_g++;
1369 #endif
1370 #endif
1371 }
1372 
1373 /*-------------------------------------------------------------------------
1374  * Function:    detect_C99_integers16
1375  *
1376  * Purpose:     Detect C99 16 bit integer types
1377  *
1378  * Return:      void
1379  *-------------------------------------------------------------------------
1380  */
1381 static void HDF_NO_UBSAN
detect_C99_integers16(void)1382 detect_C99_integers16(void)
1383 {
1384 #if H5_SIZEOF_INT16_T > 0
1385     DETECT_I(int16_t, INT16, d_g[nd_g]);
1386     nd_g++;
1387 #endif
1388 #if H5_SIZEOF_UINT16_T > 0
1389     DETECT_I(uint16_t, UINT16, d_g[nd_g]);
1390     nd_g++;
1391 #endif
1392 #if H5_SIZEOF_INT_LEAST16_T > 0
1393     DETECT_I(int_least16_t, INT_LEAST16, d_g[nd_g]);
1394     nd_g++;
1395 #endif
1396 #if H5_SIZEOF_UINT_LEAST16_T > 0
1397     DETECT_I(uint_least16_t, UINT_LEAST16, d_g[nd_g]);
1398     nd_g++;
1399 #endif
1400 #if H5_SIZEOF_INT_FAST16_T > 0
1401     DETECT_I(int_fast16_t, INT_FAST16, d_g[nd_g]);
1402     nd_g++;
1403 #endif
1404 #if H5_SIZEOF_UINT_FAST16_T > 0
1405     DETECT_I(uint_fast16_t, UINT_FAST16, d_g[nd_g]);
1406     nd_g++;
1407 #endif
1408 }
1409 
1410 /*-------------------------------------------------------------------------
1411  * Function:    detect_C99_integers32
1412  *
1413  * Purpose:     Detect C99 32 bit integer types
1414  *
1415  * Return:      void
1416  *-------------------------------------------------------------------------
1417  */
1418 static void HDF_NO_UBSAN
detect_C99_integers32(void)1419 detect_C99_integers32(void)
1420 {
1421 #if H5_SIZEOF_INT32_T > 0
1422     DETECT_I(int32_t, INT32, d_g[nd_g]);
1423     nd_g++;
1424 #endif
1425 #if H5_SIZEOF_UINT32_T > 0
1426     DETECT_I(uint32_t, UINT32, d_g[nd_g]);
1427     nd_g++;
1428 #endif
1429 #if H5_SIZEOF_INT_LEAST32_T > 0
1430     DETECT_I(int_least32_t, INT_LEAST32, d_g[nd_g]);
1431     nd_g++;
1432 #endif
1433 #if H5_SIZEOF_UINT_LEAST32_T > 0
1434     DETECT_I(uint_least32_t, UINT_LEAST32, d_g[nd_g]);
1435     nd_g++;
1436 #endif
1437 #if H5_SIZEOF_INT_FAST32_T > 0
1438     DETECT_I(int_fast32_t, INT_FAST32, d_g[nd_g]);
1439     nd_g++;
1440 #endif
1441 #if H5_SIZEOF_UINT_FAST32_T > 0
1442     DETECT_I(uint_fast32_t, UINT_FAST32, d_g[nd_g]);
1443     nd_g++;
1444 #endif
1445 }
1446 
1447 /*-------------------------------------------------------------------------
1448  * Function:    detect_C99_integers64
1449  *
1450  * Purpose:     Detect C99 64 bit integer types
1451  *
1452  * Return:      void
1453  *
1454  *-------------------------------------------------------------------------
1455  */
1456 static void HDF_NO_UBSAN
detect_C99_integers64(void)1457 detect_C99_integers64(void)
1458 {
1459 #if H5_SIZEOF_INT64_T > 0
1460     DETECT_I(int64_t, INT64, d_g[nd_g]);
1461     nd_g++;
1462 #endif
1463 #if H5_SIZEOF_UINT64_T > 0
1464     DETECT_I(uint64_t, UINT64, d_g[nd_g]);
1465     nd_g++;
1466 #endif
1467 #if H5_SIZEOF_INT_LEAST64_T > 0
1468     DETECT_I(int_least64_t, INT_LEAST64, d_g[nd_g]);
1469     nd_g++;
1470 #endif
1471 #if H5_SIZEOF_UINT_LEAST64_T > 0
1472     DETECT_I(uint_least64_t, UINT_LEAST64, d_g[nd_g]);
1473     nd_g++;
1474 #endif
1475 #if H5_SIZEOF_INT_FAST64_T > 0
1476     DETECT_I(int_fast64_t, INT_FAST64, d_g[nd_g]);
1477     nd_g++;
1478 #endif
1479 #if H5_SIZEOF_UINT_FAST64_T > 0
1480     DETECT_I(uint_fast64_t, UINT_FAST64, d_g[nd_g]);
1481     nd_g++;
1482 #endif
1483 
1484 #if H5_SIZEOF_LONG_LONG > 0
1485     DETECT_I(long long, LLONG, d_g[nd_g]);
1486     nd_g++;
1487     DETECT_I(unsigned long long, ULLONG, d_g[nd_g]);
1488     nd_g++;
1489 #else
1490     /*
1491      * This architecture doesn't support an integer type larger than `long'
1492      * so we'll just make H5T_NATIVE_LLONG the same as H5T_NATIVE_LONG since
1493      * `long long' is probably equivalent to `long' here anyway.
1494      */
1495     DETECT_I(long, LLONG, d_g[nd_g]);
1496     nd_g++;
1497     DETECT_I(unsigned long, ULLONG, d_g[nd_g]);
1498     nd_g++;
1499 #endif
1500 }
1501 
1502 /*-------------------------------------------------------------------------
1503  * Function:    detect_C99_integers
1504  *
1505  * Purpose:     Detect C99 integer types
1506  *
1507  * Return:      void
1508  *-------------------------------------------------------------------------
1509  */
1510 static void HDF_NO_UBSAN
detect_C99_integers(void)1511 detect_C99_integers(void)
1512 {
1513     /* break it down to more subroutines so that each module subroutine */
1514     /* is smaller and takes less time to compile with optimization on.  */
1515     detect_C99_integers8();
1516     detect_C99_integers16();
1517     detect_C99_integers32();
1518     detect_C99_integers64();
1519 }
1520 
1521 /*-------------------------------------------------------------------------
1522  * Function:    detect_C99_floats
1523  *
1524  * Purpose:     Detect C99 floating point types
1525  *
1526  * Return:      void
1527  *-------------------------------------------------------------------------
1528  */
1529 static void HDF_NO_UBSAN
detect_C99_floats(void)1530 detect_C99_floats(void)
1531 {
1532 #if H5_SIZEOF_DOUBLE == H5_SIZEOF_LONG_DOUBLE
1533     /*
1534      * If sizeof(double)==sizeof(long double) then assume that `long double'
1535      * isn't supported and use `double' instead.  This suppresses warnings on
1536      * some systems and `long double' is probably the same as `double' here
1537      * anyway.
1538      */
1539     DETECT_F(double, LDOUBLE, d_g[nd_g]);
1540     nd_g++;
1541 #elif H5_SIZEOF_LONG_DOUBLE != 0
1542     DETECT_F(long double, LDOUBLE, d_g[nd_g]);
1543     nd_g++;
1544 #endif
1545 }
1546 
1547 /*-------------------------------------------------------------------------
1548  * Function:    detect_alignments
1549  *
1550  * Purpose:     Detect structure alignments
1551  *
1552  * Return:      void
1553  *-------------------------------------------------------------------------
1554  */
1555 static void HDF_NO_UBSAN
detect_alignments(void)1556 detect_alignments(void)
1557 {
1558     /* Detect structure alignment for pointers, vlen and reference types */
1559     DETECT_M(void *, POINTER, m_g[na_g]);
1560     na_g++;
1561     DETECT_M(hvl_t, HVL, m_g[na_g]);
1562     na_g++;
1563     DETECT_M(hobj_ref_t, HOBJREF, m_g[na_g]);
1564     na_g++;
1565     DETECT_M(hdset_reg_ref_t, HDSETREGREF, m_g[na_g]);
1566     na_g++;
1567     DETECT_M(H5R_ref_t, REF, m_g[na_g]);
1568     na_g++;
1569 }
1570 
1571 #if defined(H5SETJMP) && defined(H5_HAVE_SIGNAL)
1572 /* Verify the signal handler for signal signum works correctly multiple times.
1573  * One possible cause of failure is that the signal handling is blocked or
1574  * changed to SIG_DFL after H5LONGJMP.
1575  * Return  0 for success, -1 for failure.
1576  */
1577 static int
verify_signal_handlers(int signum,void (* handler)(int))1578 verify_signal_handlers(int signum, void (*handler)(int))
1579 {
1580 #if defined(__has_feature) /* Clang */
1581 #if __has_feature(address_sanitizer) || __has_feature(thread_sanitizer)
1582     /* Under the address and thread sanitizers, don't raise any signals. */
1583     return 0;
1584 #endif
1585 #elif defined(__SANITIZE_ADDRESS__) || defined(__SANITIZE_THREAD__) /* GCC */
1586     return 0;
1587 #endif
1588     void (*save_handler)(int) = HDsignal(signum, handler);
1589     volatile int i, val;
1590     int          ntries     = 5;
1591     volatile int nfailures  = 0;
1592     volatile int nsuccesses = 0;
1593 
1594     for (i = 0; i < ntries; i++) {
1595         val = H5SETJMP(jbuf_g);
1596         if (val == 0) {
1597             /* send self the signal to trigger the handler */
1598             signal_handler_tested_g++;
1599             HDraise(signum);
1600             /* Should not reach here. Record error. */
1601             nfailures++;
1602         }
1603         else {
1604             if (val == signum) {
1605                 /* return from signum handler. Record a sucess. */
1606                 nsuccesses++;
1607             }
1608             else {
1609                 fprintf(stderr, "Unknown return value (%d) from H5SETJMP", val);
1610                 nfailures++;
1611             }
1612         }
1613     }
1614     /* restore save handler, check results and report failures */
1615     HDsignal(signum, save_handler);
1616     if (nfailures > 0 || nsuccesses != ntries) {
1617         fprintf(stderr,
1618                 "verify_signal_handlers for signal %d did %d tries. "
1619                 "Found %d failures and %d successes\n",
1620                 signum, ntries, nfailures, nsuccesses);
1621         return -1;
1622     }
1623     else {
1624         /* all succeeded */
1625         return 0;
1626     }
1627 }
1628 #endif
1629 
1630 /*-------------------------------------------------------------------------
1631  * Function:    main
1632  *
1633  * Purpose:     Main entry point.
1634  *
1635  * Return:      Success:    EXIT_SUCCESS
1636  *
1637  *-------------------------------------------------------------------------
1638  */
1639 int HDF_NO_UBSAN
main(int argc,char * argv[])1640 main(int argc, char *argv[])
1641 {
1642     char *fname = NULL;
1643     FILE *f; /* temporary holding place for the stream pointer
1644               * so that rawoutstream is changed only when succeeded */
1645 
1646     if (argc > 1)
1647         fname = argv[1];
1648 
1649     /* First check if filename is string "NULL" */
1650     if (fname != NULL) {
1651         /* binary output */
1652         if ((f = HDfopen(fname, "w")) != NULL)
1653             rawoutstream = f;
1654     }
1655     if (!rawoutstream)
1656         rawoutstream = stdout;
1657 
1658 #if defined(H5_HAVE_SETSYSINFO) && defined(SSI_NVPAIRS)
1659 #if defined(UAC_NOPRINT) && defined(UAC_SIGBUS)
1660     /*
1661      * Make sure unaligned access generates SIGBUS and doesn't print warning
1662      * messages so that we can detect alignment constraints on the DEC Alpha.
1663      */
1664     int nvpairs[2];
1665     nvpairs[0] = SSIN_UACPROC;
1666     nvpairs[1] = UAC_NOPRINT | UAC_SIGBUS;
1667     if (setsysinfo(SSI_NVPAIRS, nvpairs, 1, 0, 0) < 0) {
1668         fprintf(stderr, "H5detect: unable to turn off UAC handling: %s\n", HDstrerror(errno));
1669     }
1670 #endif
1671 #endif
1672 
1673 #if defined(H5SETJMP) && defined(H5_HAVE_SIGNAL)
1674     /* verify the SIGBUS and SIGSEGV handlers work properly */
1675     if (verify_signal_handlers(SIGBUS, sigbus_handler) != 0) {
1676         fprintf(stderr, "Signal handler %s for signal %d failed\n", "sigbus_handler", SIGBUS);
1677     }
1678     if (verify_signal_handlers(SIGSEGV, sigsegv_handler) != 0) {
1679         fprintf(stderr, "Signal handler %s for signal %d failed\n", "sigsegv_handler", SIGSEGV);
1680     }
1681     if (verify_signal_handlers(SIGILL, sigill_handler) != 0) {
1682         fprintf(stderr, "Signal handler %s for signal %d failed\n", "sigill_handler", SIGILL);
1683     }
1684 #else
1685     align_status_g |= STA_NoHandlerVerify;
1686 #endif
1687 
1688     print_header();
1689 
1690     /* C89 integer types */
1691     detect_C89_integers();
1692 
1693     /* C99 integer types */
1694     detect_C99_integers();
1695 
1696     /* C89 floating point types */
1697     detect_C89_floats();
1698 
1699     /* C99 floating point types */
1700     detect_C99_floats();
1701 
1702     /* Detect structure alignment */
1703     detect_alignments();
1704 
1705     print_results(nd_g, d_g, na_g, m_g);
1706 
1707     if (rawoutstream && rawoutstream != stdout) {
1708         if (HDfclose(rawoutstream))
1709             fprintf(stderr, "closing rawoutstream");
1710         else
1711             rawoutstream = NULL;
1712     }
1713 
1714     return EXIT_SUCCESS;
1715 }
1716 
1717 H5_GCC_DIAG_ON("cast-align")
1718