| /* Computed initializations before the program starts. | |
| Copyright (C) 2025-2026 Free Software Foundation, Inc. | |
| Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald | |
| This file is free software: you can redistribute it and/or modify | |
| it under the terms of the GNU Lesser General Public License as | |
| published by the Free Software Foundation; either version 2.1 of the | |
| License, or (at your option) any later version. | |
| This file is distributed in the hope that it will be useful, | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| GNU Lesser General Public License for more details. | |
| You should have received a copy of the GNU Lesser General Public License | |
| along with this program. If not, see <https://www.gnu.org/licenses/>. */ | |
| #ifndef _GL_AT_INIT_H | |
| #define _GL_AT_INIT_H | |
| /* AT_INIT (function); | |
| registers a function to be executed when the program is initialized, i.e. | |
| even before the main() function is entered. | |
| AT_FINI (function); | |
| registers a function to be executed when the program is about to exit. | |
| Similar to 'atexit (function)' or 'at_quick_exit (function)'. | |
| The function must have an empty argument list and return 'void'. | |
| An initialization function must not depend on the result of other | |
| initialization functions. The order in which the initialization functions | |
| are executed is unspecified. | |
| These macro invocations must *precede* the definition of the function. | |
| (This is necessary for clang.) | |
| These macros apply to executables. They are not supported in shared | |
| libraries. | |
| Note: It would be easy to achieve the same functionality by using a small | |
| C++ compilation unit. But it's better to stay with C all the way. */ | |
| /* This is implemented for each compiler separately. Basically, the idea is | |
| to look how the corresponding C++ compiler implements static initializations | |
| of C++ variables with a non-POD type, and do the same thing in C through a | |
| mix of pragmas and asms. */ | |
| /* For clang on native Windows (which defines both __clang__ and _MSC_VER): | |
| - Both definitions of AT_INIT work. | |
| - Only the .CRT$XCU based definition of AT_FINI works; the __destructor__ | |
| based definition of AT_FINI does not work. */ | |
| #if defined __GNUC__ || (defined __clang__ && !defined _MSC_VER) | |
| /* GCC and compatible compilers */ | |
| /* Documentation: | |
| <https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html> */ | |
| # define AT_INIT(function) \ | |
| static void __attribute__ ((__constructor__)) function (void) | |
| # define AT_FINI(function) \ | |
| static void __attribute__ ((__destructor__)) function (void) | |
| #elif defined _MSC_VER | |
| /* MSVC */ | |
| /* Taken from glib-2.83 gconstructor.h. | |
| Documentation: | |
| <https://learn.microsoft.com/en-us/cpp/c-runtime-library/crt-initialization> | |
| See also <https://stackoverflow.com/questions/1113409/>. */ | |
| /* Avoid an error in the pragma below. */ | |
| # undef read | |
| # ifdef _WIN64 | |
| # define GL_MSVC_SYMBOL_PREFIX "" | |
| # else | |
| # define GL_MSVC_SYMBOL_PREFIX "_" | |
| # endif | |
| # define AT_INIT(function) GL_MSVC_CTOR (function, GL_MSVC_SYMBOL_PREFIX) | |
| # define AT_FINI(function) GL_MSVC_DTOR (function, GL_MSVC_SYMBOL_PREFIX) | |
| # define GL_MSVC_CTOR(function,_sym_prefix) \ | |
| static void function(void); \ | |
| extern int (* _array ## function)(void); \ | |
| int function ## _wrapper(void); \ | |
| int function ## _wrapper(void) { function(); gl_at_init_dummy (_array ## function); return 0; } \ | |
| __pragma(comment(linker,"/include:" _sym_prefix # function "_wrapper")) \ | |
| __pragma(section(".CRT$XCU",read)) \ | |
| __declspec(allocate(".CRT$XCU")) int (* _array ## function)(void) = function ## _wrapper | |
| # define GL_MSVC_DTOR(function,_sym_prefix) \ | |
| static void function(void); \ | |
| extern int (* _array ## function)(void); \ | |
| int function ## _constructor(void); \ | |
| int function ## _constructor(void) { atexit (function); gl_at_init_dummy (_array ## function); return 0; } \ | |
| __pragma(comment(linker,"/include:" _sym_prefix # function "_constructor")) \ | |
| __pragma(section(".CRT$XCU",read)) \ | |
| __declspec(allocate(".CRT$XCU")) int (* _array ## function)(void) = function ## _constructor | |
| extern void gl_at_init_dummy (const void *); | |
| #elif defined __SUNPRO_C | |
| /* Sun C */ | |
| /* Needs also: #pragma init(function) */ | |
| # define AT_INIT(function) \ | |
| static void function (void) | |
| /* Needs also: #pragma fini(function) */ | |
| # define AT_FINI(function) \ | |
| static void function (void) | |
| #elif defined __xlC__ | |
| /* AIX xlc */ | |
| /* Needs also: #pragma init(function) | |
| and a C++ linker. See | |
| <https://www.ibm.com/docs/de/xl-c-and-cpp-aix/13.1.0?topic=descriptions-pragma-init-only> */ | |
| # define AT_INIT(function) \ | |
| static void function (void) | |
| /* Needs also: #pragma fini(function) | |
| and a C++ linker. See | |
| <https://www.ibm.com/docs/de/xl-c-and-cpp-aix/13.1.0?topic=descriptions-pragma-fini-only> */ | |
| # define AT_FINI(function) \ | |
| static void function (void) | |
| #else | |
| /* Another compiler */ | |
| /* This is just a dummy. It will not work. */ | |
| # define AT_INIT(function) \ | |
| static void function (void) | |
| # define AT_FINI(function) \ | |
| static void function (void) | |
| #endif | |
| #endif /* _GL_AT_INIT_H */ |