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