BRL-CAD
Loading...
Searching...
No Matches
common.h
Go to the documentation of this file.
1/* C O M M O N . H
2 * BRL-CAD
3 *
4 * Copyright (c) 2004-2026 United States Government as represented by
5 * the U.S. Army Research Laboratory.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * version 2.1 as published by the Free Software Foundation.
10 *
11 * This library is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this file; see the file named COPYING for more
18 * information.
19 */
20
21/** @addtogroup common
22 *
23 * This header wraps system and compilation-specific defines from
24 * brlcad_config.h and removes need to conditionally include
25 * brlcad_config.h everywhere based on HAVE_CONFIG_H. The common
26 * definitions are symbols common to the platform being built that are
27 * either detected via configure or hand crafted, as is the case for
28 * the win32 platform.
29 *
30 * NOTE: In order to use compile-time API, applications need to define
31 * BRLCADBUILD and HAVE_CONFIG_H before including this header.
32 *
33 */
34/** @{ */
35/** @brief Header file for the BRL-CAD common definitions. */
36/** @file common.h */
37
38#ifndef COMMON_H
39#define COMMON_H
40
41/* include the venerable config.h file. use a pregenerated one for
42 * windows when we cannot auto-generate it easily. do not include
43 * config.h if this file has been installed. (public header files
44 * should not use config defines)
45 */
46#if defined(BRLCADBUILD) && defined(HAVE_CONFIG_H)
47
48# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
49# include "brlcad_config.h"
50 /* Put Windows config after brlcad_config.h, since some of the
51 * tests in it require defines from brlcad_config.h
52 */
53# include "config_win.h"
54# else
55# include "brlcad_config.h"
56# endif /* _WIN32 */
57
58/* Simulates drand48() functionality using rand() which is assumed to
59 * exist everywhere. The range is [0, 1).
60 */
61# if !defined(HAVE_DRAND48) && !defined(drand48)
62# define drand48() ((double)rand() / (double)(RAND_MAX + 1))
63# define HAVE_DRAND48 1
64# define srand48(seed) (srand(seed))
65# define HAVE_DECL_DRAND48 1
66# elif !defined(HAVE_DECL_DRAND48) && !defined(__cplusplus)
67extern double drand48(void);
68# endif
69
70# if !defined(__cplusplus) || defined(HAVE_SHARED_RINT_TEST)
71/* make sure lrint() is provided */
72# if !defined(lrint)
73# if !defined(HAVE_LRINT)
74# define lrint(_x) (((_x) < 0.0) ? (long int)ceil((_x)-0.5) : (long int)floor((_x)+0.5))
75# elif !defined(HAVE_WINDOWS_H) && !defined(HAVE_DECL_LRINT)
76long int lrint(double x);
77# define HAVE_DECL_LRINT 1
78# endif
79# endif
80
81# if !defined(HAVE_LRINT)
82# define HAVE_LRINT 1
83# endif
84
85/* make sure rint() is provided */
86# if !defined(rint)
87# if !defined(HAVE_RINT)
88# define rint(_x) (((_x) < 0.0) ? ceil((_x)-0.5) : floor((_x)+0.5))
89# elif !defined(HAVE_WINDOWS_H) && !defined(HAVE_DECL_RINT)
90double rint(double x);
91# define HAVE_DECL_RINT 1
92# endif
93# endif
94
95# if !defined(HAVE_RINT)
96# define HAVE_RINT 1
97# endif
98# endif
99
100/* Make sure THREADLOCAL is defined, only usable on C "POD" types */
101#ifndef THREADLOCAL
102# if defined(__cplusplus) && __cplusplus >= 201103L
103# define THREADLOCAL thread_local // C++11 or newer: thread_local is standard
104# elif !defined(__cplusplus) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
105# define THREADLOCAL thread_local // C23: thread_local is standard
106# elif !defined(__cplusplus) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
107# define THREADLOCAL _Thread_local // C11: _Thread_local is standard
108# elif defined(HAVE_WINDOWS_H)
109# define THREADLOCAL __declspec(thread)
110# elif defined(__GNUC__) || defined(__clang__)
111# define THREADLOCAL __thread
112# else
113# error "Cannot define THREADLOCAL for this compiler/platform"
114# endif
115#endif
116
117/* strict c89 doesn't declare snprintf() */
118# if defined(HAVE_SNPRINTF) && !defined(HAVE_DECL_SNPRINTF) && !defined(snprintf) && !defined(__cplusplus)
119# include <stddef.h> /* for size_t */
120extern int snprintf(char *str, size_t size, const char *format, ...);
121# endif
122
123#endif /* BRLCADBUILD & HAVE_CONFIG_H */
124
125/* provide declaration markers for header externals */
126#ifndef __BEGIN_DECLS
127# ifdef __cplusplus
128# define __BEGIN_DECLS extern "C" { /**< if C++, set to extern "C" { */
129# define __END_DECLS } /**< if C++, set to } */
130# else
131# define __BEGIN_DECLS /**< if C++, set to extern "C" { */
132# define __END_DECLS /**< if C++, set to } */
133# endif
134#endif
135
136/* Because extern "C" doesn't work if we are compiling in C, if we want to
137 * specifically denote individual functions for C symbol export in both C and
138 * C++ compilation we need a conditional expression. __BEGIN_DECLS normally
139 * serves this purpose in BRL-CAD code, but for function signatures its bracket
140 * syntax isn't appropriate. We therefore define a second utility for the
141 * function declaration case: */
142#ifndef C_DECL
143# ifdef __cplusplus
144# define C_DECL extern "C" /**< if C++, set to extern "C" */
145# else
146# define C_DECL /**< if C define empty */
147# endif
148#endif
149
150
151/* ANSI c89 does not allow the 'inline' keyword, check if GNU inline
152 * rules are in effect.
153 *
154 * TODO: test removal of __STRICT_ANSI__ on Windows.
155 */
156#if !defined __cplusplus && (defined(__STRICT_ANSI__) || defined(__GNUC_GNU_INLINE__))
157# ifndef inline
158# define inline /***/
159# endif
160#endif
161
162/** Find and return the maximum value */
163#ifndef FMAX
164# define FMAX(a, b) (((a)>(b))?(a):(b))
165#endif
166/** Find and return the minimum value */
167#ifndef FMIN
168# define FMIN(a, b) (((a)<(b))?(a):(b))
169#endif
170
171/* make sure the old bsd types are defined for portability */
172#if defined(BRLCADBUILD) && defined(HAVE_CONFIG_H)
173# if !defined(HAVE_U_TYPES)
174typedef unsigned char u_char;
175typedef unsigned int u_int;
176typedef unsigned long u_long;
177typedef unsigned short u_short;
178# define HAVE_U_TYPES 1
179# endif
180#endif
181
182/* We want 64 bit (large file) I/O capabilities whenever they are available.
183 * Always define this before we include sys/types.h */
184#ifndef _FILE_OFFSET_BITS
185# define _FILE_OFFSET_BITS 64
186#endif
187
188/**
189 * make sure ssize_t is provided. C99 does not provide it even though it is
190 * defined in SUS97. if not available, we create the type aligned with the
191 * similar POSIX ptrdiff_t type.
192 */
193#if defined(_MSC_VER) && !defined(HAVE_SSIZE_T)
194# ifdef HAVE_SYS_TYPES_H
195# include <sys/types.h>
196# endif
197# include <limits.h>
198# include <stddef.h>
199typedef ptrdiff_t ssize_t;
200# define HAVE_SSIZE_T 1
201# ifndef SSIZE_MAX
202# if defined(LONG_MAX)
203# define SSIZE_MAX LONG_MAX
204# elif defined(INT_MAX)
205# define SSIZE_MAX INT_MAX
206# elif defined(_POSIX_SSIZE_MAX)
207# define SSIZE_MAX _POSIX_SSIZE_MAX
208# else
209 /* Go with POSIX minimum acceptable value. This is smaller than
210 * we would like, but is a safe default value.
211 */
212# define SSIZE_MAX 32767
213# endif
214# endif
215#endif
216
217/* make sure most of the C99 stdint types are provided including the
218 * optional uintptr_t type.
219 */
220#if !defined(INT8_MAX) || !defined(INT16_MAX) || !defined(INT32_MAX) || !defined(INT64_MAX)
221# if (defined _MSC_VER && (_MSC_VER <= 1500))
222 /* Older Versions of Visual C++ seem to need pstdint.h but still
223 * pass the tests below, so force it based on version (ugh.)
224 */
225# include "pstdint.h"
226# elif defined(__STDC__) || defined(__STRICT_ANSI__) || defined(__SIZE_TYPE__) || defined(HAVE_STDINT_H)
227# if !defined(__STDC_LIMIT_MACROS)
228# define __STDC_LIMIT_MACROS 1
229# endif
230# if !defined(__STDC_CONSTANT_MACROS)
231# define __STDC_CONSTANT_MACROS 1
232# endif
233# include <stdint.h>
234# else
235# include "pstdint.h"
236# endif
237#endif
238
239/* off_t is 32 bit size even on 64 bit Windows. In the past we have tried to
240 * force off_t to be 64 bit but this is failing on newer Windows/Visual Studio
241 * versions in 2020 - therefore, we instead introduce the b_off_t define to
242 * properly substitute the correct numerical type for the correct platform. */
243#if defined(_WIN64)
244# include <sys/stat.h>
245# define b_off_t __int64
246# define fstat _fstati64
247# define stat _stati64
248#elif defined (_WIN32)
249# include <sys/stat.h>
250# define b_off_t _off_t
251# define fstat _fstat
252# define stat _stat
253#else
254# define b_off_t off_t
255#endif
256
257/**
258 * Maximum length of a filesystem path. Typically defined in a system
259 * file but if it isn't set, we create it.
260 */
261#ifndef MAXPATHLEN
262# include <limits.h> // Consistently define (or not) PATH_MAX
263# ifdef PATH_MAX
264# define MAXPATHLEN PATH_MAX
265# elif defined(MAX_PATH)
266# define MAXPATHLEN MAX_PATH
267# elif defined(_MAX_PATH)
268# define MAXPATHLEN _MAX_PATH
269# else
270# define MAXPATHLEN 2048
271# endif
272#endif
273
274/**
275 * Provide a means to conveniently test the version of the GNU
276 * compiler. Use it like this:
277 *
278 * @code
279 * #if GCC_PREREQ(2,8)
280 * ... code requiring gcc 2.8 or later ...
281 * #endif
282 * @endcode
283 *
284 * WARNING: THIS MACRO IS CONSIDERED PRIVATE AND SHOULD NOT BE USED
285 * OUTSIDE OF THIS HEADER FILE. DO NOT RELY ON IT.
286 */
287#ifdef GCC_PREREQ
288# warning "GCC_PREREQ unexpectedly defined. Ensure common.h is included first."
289# undef GCC_PREREQ
290#endif
291#if defined __GNUC__
292# define GCC_PREREQ(major, minor) __GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))
293#else
294# define GCC_PREREQ(major, minor) 0
295#endif
296
297/**
298 * Provide a means to conveniently test the version of the Intel
299 * compiler. Use it like this:
300 *
301 * @code
302 * #if ICC_PREREQ(800)
303 * ... code requiring icc 8.0 or later ...
304 * #endif
305 * @endcode
306 *
307 * WARNING: THIS MACRO IS CONSIDERED PRIVATE AND SHOULD NOT BE USED
308 * OUTSIDE OF THIS HEADER FILE. DO NOT RELY ON IT.
309 */
310/* provide a means to conveniently test the version of ICC */
311#ifdef ICC_PREREQ
312# warning "ICC_PREREQ unexpectedly defined. Ensure common.h is included first."
313# undef ICC_PREREQ
314#endif
315#if defined __INTEL_COMPILER
316# define ICC_PREREQ(version) (__INTEL_COMPILER >= (version))
317#else
318# define ICC_PREREQ(version) 0
319#endif
320
321/* This is so we can use gcc's "format string vs arguments"-check for
322 * various printf-like functions, and still maintain compatibility.
323 */
324#ifndef __attribute__
325/* This feature is only available in gcc versions 2.5 and later. */
326# if !GCC_PREREQ(2, 5)
327# define __attribute__(ignore) /* empty */
328# endif
329/* The __-protected variants of `format' and `printf' attributes
330 * are accepted by gcc versions 2.6.4 (effectively 2.7) and later.
331 */
332# if !GCC_PREREQ(2, 7)
333# define __format__ format
334# define __printf__ printf
335# define __noreturn__ noreturn
336# endif
337#endif
338
339/* gcc 3.4 doesn't seem to support always_inline with -O0 (yet -Os
340 * reportedly works), so turn it off.
341 */
342#if !GCC_PREREQ(3, 5)
343# define always_inline noinline
344#endif
345
346/**
347 * UNUSED provides a common mechanism for declaring unused parameters.
348 * Use it like this:
349 *
350 * int
351 * my_function(int argc, char **UNUSED(argv))
352 * {
353 * ...
354 * }
355 *
356 */
357#ifdef UNUSED
358# warning "UNUSED unexpectedly defined. Ensure common.h is included first."
359# undef UNUSED
360#endif
361#if GCC_PREREQ(2, 5)
362/* GCC-style compilers have an attribute */
363# define UNUSED(parameter) UNUSED_ ## parameter __attribute__((unused))
364#elif defined(__cplusplus)
365/* C++ allows the name to go away */
366# define UNUSED(parameter) /* parameter */
367#else
368/* some are asserted when !NDEBUG */
369# define UNUSED(parameter) (parameter)
370#endif
371
372/**
373 * LIKELY provides a common mechanism for providing branch prediction
374 * hints to the compiler so that it can better optimize. It should be
375 * used when it's exceptionally likely that an expected code path will
376 * almost always be executed. Use it like this:
377 *
378 * if (LIKELY(x == 1)) {
379 * ... expected code path ...
380 * }
381 *
382 */
383#ifdef LIKELY
384# undef LIKELY
385# warning "LIKELY unexpectedly defined. Ensure common.h is included first."
386#endif
387#if GCC_PREREQ(3, 0) || ICC_PREREQ(800)
388# define LIKELY(expression) __builtin_expect((expression), 1)
389#else
390# define LIKELY(expression) (expression)
391#endif
392
393/**
394 * UNLIKELY provides a common mechanism for providing branch
395 * prediction hints to the compiler so that it can better optimize.
396 * It should be used when it's exceptionally unlikely that a given code
397 * path will ever be executed. Use it like this:
398 *
399 * if (UNLIKELY(x == 0)) {
400 * ... unexpected code path ...
401 * }
402 *
403 */
404#ifdef UNLIKELY
405# undef UNLIKELY
406# warning "UNLIKELY unexpectedly defined. Ensure common.h is included first."
407#endif
408#if GCC_PREREQ(3, 0) || ICC_PREREQ(800)
409# define UNLIKELY(expression) __builtin_expect((expression), 0)
410#else
411# define UNLIKELY(expression) (expression)
412#endif
413
414/**
415 * DEPRECATED provides a common mechanism for denoting public API
416 * (e.g., functions, typedefs, variables) that is considered
417 * deprecated. Use it like this:
418 *
419 * DEPRECATED int my_function(void);
420 *
421 * typedef struct karma some_type DEPRECATED;
422 */
423#ifdef DEPRECATED
424# undef DEPRECATED
425# warning "DEPRECATED unexpectedly defined. Ensure common.h is included first."
426#endif
427#if GCC_PREREQ(3, 1) || ICC_PREREQ(800)
428# define DEPRECATED __attribute__((deprecated))
429#elif defined(_WIN32)
430# define DEPRECATED __declspec(deprecated("This function is DEPRECATED. Please update code to new API."))
431#else
432# define DEPRECATED /* deprecated */
433#endif
434
435
436/**
437 * NORETURN declares that a function does not return.
438 *
439 * For portability, the attribute must precede the function, i.e., be
440 * declared on the left:
441 *
442 * NORETURN void function(void);
443 *
444 * Note that throwing an exception or calling longjmp() do not
445 * constitute a return. Functions that (always) infinite loop can be
446 * considered functions that do not return. Functions that do not
447 * return should have a void return type. This option is a hint to
448 * compilers and static analyzers, to reduce false positive reporting.
449 */
450#ifdef NORETURN
451# undef NORETURN
452# warning "NORETURN unexpectedly defined. Ensure common.h is included first."
453#endif
454#if defined(HAVE_NORETURN_ATTRIBUTE)
455# define NORETURN __attribute__((__noreturn__))
456#elif defined(HAVE_NORETURN_DECLSPEC)
457# define NORETURN __declspec(noreturn)
458#else
459# define NORETURN /* does not return */
460#endif
461
462
463/**
464 * FAUX_NORETURN declares a function should be treated as if it does
465 * not return, even though it can.
466 *
467 * As this label is (currently) Clang-specific, it can be declared on
468 * the left or right of a function declaration. Left is recommended
469 * for consistency with other annotations, e.g.:
470 *
471 * FAUX_NORETURN void function(void);
472 *
473 * This annocation is almost identical to NORETURN except that it does
474 * not affect code generation and can be used on functions that
475 * actually return. It's typically useful for annotating assertion
476 * handlers (e.g., assert()) that sometimes return and should not be
477 * used on NORETURN functions. This annotation is primarily a hint to
478 * static analyzers.
479 */
480#ifdef FAUX_NORETURN
481# undef FAUX_NORETURN
482# warning "FAUX_NORETURN unexpectedly defined. Ensure common.h is included first."
483#endif
484#ifdef HAVE_ANALYZER_NORETURN_ATTRIBUTE
485# define FAUX_NORETURN __attribute__((analyzer_noreturn))
486#else
487# define FAUX_NORETURN /* pretend does not return */
488#endif
489
490
491/* ActiveState Tcl doesn't include this catch in tclPlatDecls.h, so we
492 * have to add it for them
493 */
494#if defined(_MSC_VER) && defined(__STDC__)
495# include <tchar.h>
496/* MSVC++ misses this. */
497typedef _TCHAR TCHAR;
498#endif
499
500/* Avoid -Wundef warnings for system headers that use __STDC_VERSION__ without
501 * checking if it's defined.
502 */
503#if !defined(__STDC_VERSION__)
504# define __STDC_VERSION__ 0
505#endif
506
507
508/* workaround for system Eigen on Mac which uses alloca without proper includes */
509#if defined(__APPLE__) && !defined(alloca)
510# define alloca(x) malloc(x)
511#endif
512
513/**
514 * globally disable certain warnings. do NOT add new warnings here
515 * without discussion and research. only warnings that cannot be
516 * quieted without objectively decreasing code quality should be
517 * added! even warnings that are innocuous or produce false-positive
518 * should be quelled when possible.
519 *
520 * any warnings added should include a description and justification.
521 */
522#if defined(_MSC_VER)
523
524/* /W1 warning C4351: new behavior: elements of array '...' will be default initialized
525 *
526 * i.e., this is the "we now implement constructor member
527 * initialization correctly" warning that tells the user an
528 * initializer like this:
529 *
530 * Class::Class() : some_array() {}
531 *
532 * will now initialize all members of some_array. previous to
533 * MSVC2005, behavior was to not initialize in some cases...
534 */
535# pragma warning( disable : 4351 )
536
537/* warning C5105: macro expansion producing 'defined' has undefined behavior
538 *
539 * this appears to be an erroneous issue in the latest msvc
540 * pre-processor that has support for the new C17 standard, which
541 * triggers warnings in Windows SDK headers (e.g., winbase.h) that
542 * use the defined operator in certain macros.
543 */
544# pragma warning( disable : 5105 )
545
546/* dubious warnings that are not yet intentionally disabled:
547 *
548 * /W3 warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)
549 *
550 * this warning is caused by assigning an int (or other non-boolean
551 * value) to a bool like this:
552 *
553 * int i = 1; bool b = i;
554 *
555 * there is something to be said for making such assignments explicit,
556 * e.g., "b = (i != 0);", but this arguably decreases readability or
557 * clarity and the fix has potential for introducing logic errors.
558 */
559/*# pragma warning( disable : 4800 ) */
560
561#endif
562
563/**
564 * Provide a macro for different treatment of initialized extern const
565 * variables between C and C++. In C the following initialization
566 * (definition) is acceptable for external linkage:
567 *
568 * const int var = 10;
569 *
570 * but in C++ const is implicitly internal linkage so it must have
571 * extern qualifier:
572 *
573 * extern const int var = 10;
574 *
575 * In a lot of situations you can just use "extern" for both C and
576 * C++, but there are some trickier cases (src/rt is one example)
577 * where it is simpler to do things this way.
578 */
579#if defined(__cplusplus)
580# define EXTERNCPP extern
581#else
582# define EXTERNCPP
583#endif
584
585/**
586 * Provide canonical preprocessor stringification.
587 *
588 @code
589 * #define abc 123
590 * CPP_STR(abc) => "abc"
591 @endcode
592 */
593#ifndef CPP_STR
594# define CPP_STR(x) # x
595#endif
596
597/**
598 * Provide canonical preprocessor expanded stringification.
599 *
600 @code
601 * #define abc 123
602 * CPP_XSTR(abc) => "123"
603 @endcode
604 */
605#ifndef CPP_XSTR
606# define CPP_XSTR(x) CPP_STR(x)
607#endif
608
609/**
610 * Provide canonical preprocessor concatenation.
611 *
612 @code
613 * #define abc 123
614 * CPP_GLUE(abc, 123) => abc123
615 * CPP_STR(CPP_GLUE(abc, 123)) => "CPP_GLUE(abc, 123)"
616 * CPP_XSTR(CPP_GLUE(abc, 123)) => "abc123"
617 * #define abc123 "xyz"
618 * CPP_GLUE(abc, 123) => abc123 => "xyz"
619 @endcode
620 */
621#ifndef CPP_GLUE
622# define CPP_GLUE(a, b) a ## b
623#endif
624
625/**
626 * Provide canonical preprocessor expanded concatenation.
627 *
628 @code
629 * #define abc 123
630 * CPP_XGLUE(abc, 123) => 123123
631 * CPP_STR(CPP_XGLUE(abc, 123)) => "CPP_XGLUE(abc, 123)"
632 * CPP_XSTR(CPP_XGLUE(abc, 123)) => "123123"
633 @endcode
634 */
635#ifndef CPP_XGLUE
636# define CPP_XGLUE(a, b) CPP_GLUE(a, b)
637#endif
638
639/**
640 * Provide format specifier string tied to a size (e.g., "%123s")
641 *
642 @code
643 * #define STR_LEN 10+1
644 * char str[STR_LEN] = {0};
645 * scanf(CPP_SCANSIZE(STR_LEN) "\n", str);
646 @endcode
647 */
648#ifndef CPP_SCAN
649# define CPP_SCAN(sz) "%" CPP_XSTR(sz) "s"
650#endif
651
652/**
653 * Provide the current filename and linenumber as a static
654 * preprocessor string in "file"":""line" format (e.g., "file:123").
655 */
656#ifndef CPP_FILELINE
657# define CPP_FILELINE __FILE__ ":" CPP_XSTR(__LINE__)
658#endif
659
660/**
661 * If we've not already defined COMPILER_DLLEXPORT and COMPILER_DLLIMPORT,
662 * define them away so code including the *_EXPORT header logic won't
663 * fail.
664 */
665#if defined(_MSC_VER)
666# define COMPILER_DLLEXPORT __declspec(dllexport)
667# define COMPILER_DLLIMPORT __declspec(dllimport)
668#elif defined(__GNUC__) || defined(__clang__)
669# define COMPILER_DLLEXPORT __attribute__ ((visibility ("default")))
670# define COMPILER_DLLIMPORT __attribute__ ((visibility ("default")))
671#else
672# define COMPILER_DLLEXPORT
673# define COMPILER_DLLIMPORT
674#endif
675
676#endif /* COMMON_H */
677
678/** @} */
679/*
680 * Local Variables:
681 * mode: C
682 * tab-width: 8
683 * indent-tabs-mode: t
684 * c-file-style: "stroustrup"
685 * End:
686 * ex: shiftwidth=4 tabstop=8
687 */
Definition dvec.h:74