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-2025 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/* ANSI c89 does not allow the 'inline' keyword, check if GNU inline
137 * rules are in effect.
138 *
139 * TODO: test removal of __STRICT_ANSI__ on Windows.
140 */
141#if !defined __cplusplus && (defined(__STRICT_ANSI__) || defined(__GNUC_GNU_INLINE__))
142# ifndef inline
143# define inline /***/
144# endif
145#endif
146
147/** Find and return the maximum value */
148#ifndef FMAX
149# define FMAX(a, b) (((a)>(b))?(a):(b))
150#endif
151/** Find and return the minimum value */
152#ifndef FMIN
153# define FMIN(a, b) (((a)<(b))?(a):(b))
154#endif
155
156/* make sure the old bsd types are defined for portability */
157#if defined(BRLCADBUILD) && defined(HAVE_CONFIG_H)
158# if !defined(HAVE_U_TYPES)
159typedef unsigned char u_char;
160typedef unsigned int u_int;
161typedef unsigned long u_long;
162typedef unsigned short u_short;
163# define HAVE_U_TYPES 1
164# endif
165#endif
166
167/* We want 64 bit (large file) I/O capabilities whenever they are available.
168 * Always define this before we include sys/types.h */
169#ifndef _FILE_OFFSET_BITS
170# define _FILE_OFFSET_BITS 64
171#endif
172
173/**
174 * make sure ssize_t is provided. C99 does not provide it even though it is
175 * defined in SUS97. if not available, we create the type aligned with the
176 * similar POSIX ptrdiff_t type.
177 */
178#if defined(_MSC_VER) && !defined(HAVE_SSIZE_T)
179# ifdef HAVE_SYS_TYPES_H
180# include <sys/types.h>
181# endif
182# include <limits.h>
183# include <stddef.h>
184typedef ptrdiff_t ssize_t;
185# define HAVE_SSIZE_T 1
186# ifndef SSIZE_MAX
187# if defined(LONG_MAX)
188# define SSIZE_MAX LONG_MAX
189# elif defined(INT_MAX)
190# define SSIZE_MAX INT_MAX
191# elif defined(_POSIX_SSIZE_MAX)
192# define SSIZE_MAX _POSIX_SSIZE_MAX
193# else
194 /* Go with POSIX minimum acceptable value. This is smaller than
195 * we would like, but is a safe default value.
196 */
197# define SSIZE_MAX 32767
198# endif
199# endif
200#endif
201
202/* make sure most of the C99 stdint types are provided including the
203 * optional uintptr_t type.
204 */
205#if !defined(INT8_MAX) || !defined(INT16_MAX) || !defined(INT32_MAX) || !defined(INT64_MAX)
206# if (defined _MSC_VER && (_MSC_VER <= 1500))
207 /* Older Versions of Visual C++ seem to need pstdint.h but still
208 * pass the tests below, so force it based on version (ugh.)
209 */
210# include "pstdint.h"
211# elif defined(__STDC__) || defined(__STRICT_ANSI__) || defined(__SIZE_TYPE__) || defined(HAVE_STDINT_H)
212# if !defined(__STDC_LIMIT_MACROS)
213# define __STDC_LIMIT_MACROS 1
214# endif
215# if !defined(__STDC_CONSTANT_MACROS)
216# define __STDC_CONSTANT_MACROS 1
217# endif
218# include <stdint.h>
219# else
220# include "pstdint.h"
221# endif
222#endif
223
224/* off_t is 32 bit size even on 64 bit Windows. In the past we have tried to
225 * force off_t to be 64 bit but this is failing on newer Windows/Visual Studio
226 * versions in 2020 - therefore, we instead introduce the b_off_t define to
227 * properly substitute the correct numerical type for the correct platform. */
228#if defined(_WIN64)
229# include <sys/stat.h>
230# define b_off_t __int64
231# define fstat _fstati64
232# define stat _stati64
233#elif defined (_WIN32)
234# include <sys/stat.h>
235# define b_off_t _off_t
236# define fstat _fstat
237# define stat _stat
238#else
239# define b_off_t off_t
240#endif
241
242/**
243 * Maximum length of a filesystem path. Typically defined in a system
244 * file but if it isn't set, we create it.
245 */
246#ifndef MAXPATHLEN
247# include <limits.h> // Consistently define (or not) PATH_MAX
248# ifdef PATH_MAX
249# define MAXPATHLEN PATH_MAX
250# elif defined(MAX_PATH)
251# define MAXPATHLEN MAX_PATH
252# elif defined(_MAX_PATH)
253# define MAXPATHLEN _MAX_PATH
254# else
255# define MAXPATHLEN 2048
256# endif
257#endif
258
259/**
260 * Provide a means to conveniently test the version of the GNU
261 * compiler. Use it like this:
262 *
263 * @code
264 * #if GCC_PREREQ(2,8)
265 * ... code requiring gcc 2.8 or later ...
266 * #endif
267 * @endcode
268 *
269 * WARNING: THIS MACRO IS CONSIDERED PRIVATE AND SHOULD NOT BE USED
270 * OUTSIDE OF THIS HEADER FILE. DO NOT RELY ON IT.
271 */
272#ifdef GCC_PREREQ
273# warning "GCC_PREREQ unexpectedly defined. Ensure common.h is included first."
274# undef GCC_PREREQ
275#endif
276#if defined __GNUC__
277# define GCC_PREREQ(major, minor) __GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))
278#else
279# define GCC_PREREQ(major, minor) 0
280#endif
281
282/**
283 * Provide a means to conveniently test the version of the Intel
284 * compiler. Use it like this:
285 *
286 * @code
287 * #if ICC_PREREQ(800)
288 * ... code requiring icc 8.0 or later ...
289 * #endif
290 * @endcode
291 *
292 * WARNING: THIS MACRO IS CONSIDERED PRIVATE AND SHOULD NOT BE USED
293 * OUTSIDE OF THIS HEADER FILE. DO NOT RELY ON IT.
294 */
295/* provide a means to conveniently test the version of ICC */
296#ifdef ICC_PREREQ
297# warning "ICC_PREREQ unexpectedly defined. Ensure common.h is included first."
298# undef ICC_PREREQ
299#endif
300#if defined __INTEL_COMPILER
301# define ICC_PREREQ(version) (__INTEL_COMPILER >= (version))
302#else
303# define ICC_PREREQ(version) 0
304#endif
305
306/* This is so we can use gcc's "format string vs arguments"-check for
307 * various printf-like functions, and still maintain compatibility.
308 */
309#ifndef __attribute__
310/* This feature is only available in gcc versions 2.5 and later. */
311# if !GCC_PREREQ(2, 5)
312# define __attribute__(ignore) /* empty */
313# endif
314/* The __-protected variants of `format' and `printf' attributes
315 * are accepted by gcc versions 2.6.4 (effectively 2.7) and later.
316 */
317# if !GCC_PREREQ(2, 7)
318# define __format__ format
319# define __printf__ printf
320# define __noreturn__ noreturn
321# endif
322#endif
323
324/* gcc 3.4 doesn't seem to support always_inline with -O0 (yet -Os
325 * reportedly works), so turn it off.
326 */
327#if !GCC_PREREQ(3, 5)
328# define always_inline noinline
329#endif
330
331/**
332 * UNUSED provides a common mechanism for declaring unused parameters.
333 * Use it like this:
334 *
335 * int
336 * my_function(int argc, char **UNUSED(argv))
337 * {
338 * ...
339 * }
340 *
341 */
342#ifdef UNUSED
343# warning "UNUSED unexpectedly defined. Ensure common.h is included first."
344# undef UNUSED
345#endif
346#if GCC_PREREQ(2, 5)
347/* GCC-style compilers have an attribute */
348# define UNUSED(parameter) UNUSED_ ## parameter __attribute__((unused))
349#elif defined(__cplusplus)
350/* C++ allows the name to go away */
351# define UNUSED(parameter) /* parameter */
352#else
353/* some are asserted when !NDEBUG */
354# define UNUSED(parameter) (parameter)
355#endif
356
357/**
358 * LIKELY provides a common mechanism for providing branch prediction
359 * hints to the compiler so that it can better optimize. It should be
360 * used when it's exceptionally likely that an expected code path will
361 * almost always be executed. Use it like this:
362 *
363 * if (LIKELY(x == 1)) {
364 * ... expected code path ...
365 * }
366 *
367 */
368#ifdef LIKELY
369# undef LIKELY
370# warning "LIKELY unexpectedly defined. Ensure common.h is included first."
371#endif
372#if GCC_PREREQ(3, 0) || ICC_PREREQ(800)
373# define LIKELY(expression) __builtin_expect((expression), 1)
374#else
375# define LIKELY(expression) (expression)
376#endif
377
378/**
379 * UNLIKELY provides a common mechanism for providing branch
380 * prediction hints to the compiler so that it can better optimize.
381 * It should be used when it's exceptionally unlikely that a given code
382 * path will ever be executed. Use it like this:
383 *
384 * if (UNLIKELY(x == 0)) {
385 * ... unexpected code path ...
386 * }
387 *
388 */
389#ifdef UNLIKELY
390# undef UNLIKELY
391# warning "UNLIKELY unexpectedly defined. Ensure common.h is included first."
392#endif
393#if GCC_PREREQ(3, 0) || ICC_PREREQ(800)
394# define UNLIKELY(expression) __builtin_expect((expression), 0)
395#else
396# define UNLIKELY(expression) (expression)
397#endif
398
399/**
400 * DEPRECATED provides a common mechanism for denoting public API
401 * (e.g., functions, typedefs, variables) that is considered
402 * deprecated. Use it like this:
403 *
404 * DEPRECATED int my_function(void);
405 *
406 * typedef struct karma some_type DEPRECATED;
407 */
408#ifdef DEPRECATED
409# undef DEPRECATED
410# warning "DEPRECATED unexpectedly defined. Ensure common.h is included first."
411#endif
412#if GCC_PREREQ(3, 1) || ICC_PREREQ(800)
413# define DEPRECATED __attribute__((deprecated))
414#elif defined(_WIN32)
415# define DEPRECATED __declspec(deprecated("This function is DEPRECATED. Please update code to new API."))
416#else
417# define DEPRECATED /* deprecated */
418#endif
419
420
421/**
422 * NORETURN declares that a function does not return.
423 *
424 * For portability, the attribute must precede the function, i.e., be
425 * declared on the left:
426 *
427 * NORETURN void function(void);
428 *
429 * Note that throwing an exception or calling longjmp() do not
430 * constitute a return. Functions that (always) infinite loop can be
431 * considered functions that do not return. Functions that do not
432 * return should have a void return type. This option is a hint to
433 * compilers and static analyzers, to reduce false positive reporting.
434 */
435#ifdef NORETURN
436# undef NORETURN
437# warning "NORETURN unexpectedly defined. Ensure common.h is included first."
438#endif
439#if defined(HAVE_NORETURN_ATTRIBUTE)
440# define NORETURN __attribute__((__noreturn__))
441#elif defined(HAVE_NORETURN_DECLSPEC)
442# define NORETURN __declspec(noreturn)
443#else
444# define NORETURN /* does not return */
445#endif
446
447
448/**
449 * FAUX_NORETURN declares a function should be treated as if it does
450 * not return, even though it can.
451 *
452 * As this label is (currently) Clang-specific, it can be declared on
453 * the left or right of a function declaration. Left is recommended
454 * for consistency with other annotations, e.g.:
455 *
456 * FAUX_NORETURN void function(void);
457 *
458 * This annocation is almost identical to NORETURN except that it does
459 * not affect code generation and can be used on functions that
460 * actually return. It's typically useful for annotating assertion
461 * handlers (e.g., assert()) that sometimes return and should not be
462 * used on NORETURN functions. This annotation is primarily a hint to
463 * static analyzers.
464 */
465#ifdef FAUX_NORETURN
466# undef FAUX_NORETURN
467# warning "FAUX_NORETURN unexpectedly defined. Ensure common.h is included first."
468#endif
469#ifdef HAVE_ANALYZER_NORETURN_ATTRIBUTE
470# define FAUX_NORETURN __attribute__((analyzer_noreturn))
471#else
472# define FAUX_NORETURN /* pretend does not return */
473#endif
474
475
476/* ActiveState Tcl doesn't include this catch in tclPlatDecls.h, so we
477 * have to add it for them
478 */
479#if defined(_MSC_VER) && defined(__STDC__)
480# include <tchar.h>
481/* MSVC++ misses this. */
482typedef _TCHAR TCHAR;
483#endif
484
485/* Avoid -Wundef warnings for system headers that use __STDC_VERSION__ without
486 * checking if it's defined.
487 */
488#if !defined(__STDC_VERSION__)
489# define __STDC_VERSION__ 0
490#endif
491
492
493/* workaround for system Eigen on Mac which uses alloca without proper includes */
494#if defined(__APPLE__) && !defined(alloca)
495# define alloca(x) malloc(x)
496#endif
497
498/**
499 * globally disable certain warnings. do NOT add new warnings here
500 * without discussion and research. only warnings that cannot be
501 * quieted without objectively decreasing code quality should be
502 * added! even warnings that are innocuous or produce false-positive
503 * should be quelled when possible.
504 *
505 * any warnings added should include a description and justification.
506 */
507#if defined(_MSC_VER)
508
509/* /W1 warning C4351: new behavior: elements of array '...' will be default initialized
510 *
511 * i.e., this is the "we now implement constructor member
512 * initialization correctly" warning that tells the user an
513 * initializer like this:
514 *
515 * Class::Class() : some_array() {}
516 *
517 * will now initialize all members of some_array. previous to
518 * MSVC2005, behavior was to not initialize in some cases...
519 */
520# pragma warning( disable : 4351 )
521
522/* warning C5105: macro expansion producing 'defined' has undefined behavior
523 *
524 * this appears to be an erroneous issue in the latest msvc
525 * pre-processor that has support for the new C17 standard, which
526 * triggers warnings in Windows SDK headers (e.g., winbase.h) that
527 * use the defined operator in certain macros.
528 */
529# pragma warning( disable : 5105 )
530
531/* dubious warnings that are not yet intentionally disabled:
532 *
533 * /W3 warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)
534 *
535 * this warning is caused by assigning an int (or other non-boolean
536 * value) to a bool like this:
537 *
538 * int i = 1; bool b = i;
539 *
540 * there is something to be said for making such assignments explicit,
541 * e.g., "b = (i != 0);", but this arguably decreases readability or
542 * clarity and the fix has potential for introducing logic errors.
543 */
544/*# pragma warning( disable : 4800 ) */
545
546#endif
547
548/**
549 * Provide a macro for different treatment of initialized extern const
550 * variables between C and C++. In C the following initialization
551 * (definition) is acceptable for external linkage:
552 *
553 * const int var = 10;
554 *
555 * but in C++ const is implicitly internal linkage so it must have
556 * extern qualifier:
557 *
558 * extern const int var = 10;
559 */
560#if defined(__cplusplus)
561# define EXTERNVARINIT extern
562#else
563# define EXTERNVARINIT
564#endif
565
566/**
567 * Provide canonical preprocessor stringification.
568 *
569 @code
570 * #define abc 123
571 * CPP_STR(abc) => "abc"
572 @endcode
573 */
574#ifndef CPP_STR
575# define CPP_STR(x) # x
576#endif
577
578/**
579 * Provide canonical preprocessor expanded stringification.
580 *
581 @code
582 * #define abc 123
583 * CPP_XSTR(abc) => "123"
584 @endcode
585 */
586#ifndef CPP_XSTR
587# define CPP_XSTR(x) CPP_STR(x)
588#endif
589
590/**
591 * Provide canonical preprocessor concatenation.
592 *
593 @code
594 * #define abc 123
595 * CPP_GLUE(abc, 123) => abc123
596 * CPP_STR(CPP_GLUE(abc, 123)) => "CPP_GLUE(abc, 123)"
597 * CPP_XSTR(CPP_GLUE(abc, 123)) => "abc123"
598 * #define abc123 "xyz"
599 * CPP_GLUE(abc, 123) => abc123 => "xyz"
600 @endcode
601 */
602#ifndef CPP_GLUE
603# define CPP_GLUE(a, b) a ## b
604#endif
605
606/**
607 * Provide canonical preprocessor expanded concatenation.
608 *
609 @code
610 * #define abc 123
611 * CPP_XGLUE(abc, 123) => 123123
612 * CPP_STR(CPP_XGLUE(abc, 123)) => "CPP_XGLUE(abc, 123)"
613 * CPP_XSTR(CPP_XGLUE(abc, 123)) => "123123"
614 @endcode
615 */
616#ifndef CPP_XGLUE
617# define CPP_XGLUE(a, b) CPP_GLUE(a, b)
618#endif
619
620/**
621 * Provide format specifier string tied to a size (e.g., "%123s")
622 *
623 @code
624 * #define STR_LEN 10+1
625 * char str[STR_LEN] = {0};
626 * scanf(CPP_SCANSIZE(STR_LEN) "\n", str);
627 @endcode
628 */
629#ifndef CPP_SCAN
630# define CPP_SCAN(sz) "%" CPP_XSTR(sz) "s"
631#endif
632
633/**
634 * Provide the current filename and linenumber as a static
635 * preprocessor string in "file"":""line" format (e.g., "file:123").
636 */
637#ifndef CPP_FILELINE
638# define CPP_FILELINE __FILE__ ":" CPP_XSTR(__LINE__)
639#endif
640
641/**
642 * If we've not already defined COMPILER_DLLEXPORT and COMPILER_DLLIMPORT,
643 * define them away so code including the *_EXPORT header logic won't
644 * fail.
645 */
646#if defined(_MSC_VER)
647# define COMPILER_DLLEXPORT __declspec(dllexport)
648# define COMPILER_DLLIMPORT __declspec(dllimport)
649#elif defined(__GNUC__) || defined(__clang__)
650# define COMPILER_DLLEXPORT __attribute__ ((visibility ("default")))
651# define COMPILER_DLLIMPORT __attribute__ ((visibility ("default")))
652#else
653# define COMPILER_DLLEXPORT
654# define COMPILER_DLLIMPORT
655#endif
656
657#endif /* COMMON_H */
658
659/** @} */
660/*
661 * Local Variables:
662 * mode: C
663 * tab-width: 8
664 * indent-tabs-mode: t
665 * c-file-style: "stroustrup"
666 * End:
667 * ex: shiftwidth=4 tabstop=8
668 */
Definition dvec.h:74
void float float int int int int float * size
Definition tig.h:132
void float * x
Definition tig.h:72