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