autoinit_funcs.h (25654B)
1 /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ 2 /* 3 AutoinitFuncs: Automatic Initialisation and Deinitialisation Functions 4 Copyright(C) 2014-2024 Karlson2k (Evgeny Grin) 5 6 This header is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 This header is distributed in the hope that it will be useful, 12 but 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 Alternatively, you can redistribute GNU This header and/or 17 modify it under the terms of the GNU General Public License as 18 published by the Free Software Foundation; either version 2 of 19 the License, or (at your option) any later version, together 20 with the eCos exception, as follows: 21 22 As a special exception, if other files instantiate templates or 23 use macros or inline functions from this file, or you compile this 24 file and link it with other works to produce a work based on this 25 file, this file does not by itself cause the resulting work to be 26 covered by the GNU General Public License. However the source code 27 for this file must still be made available in accordance with 28 section (3) of the GNU General Public License v2. 29 30 This exception does not invalidate any other reasons why a work 31 based on this file might be covered by the GNU General Public 32 License. 33 34 You should have received copies of the GNU Lesser General Public 35 License and the GNU General Public License along with this header; 36 if not, see <https://www.gnu.org/licenses/>. 37 */ 38 39 /* 40 General usage is simple: include this header, define two functions 41 with zero parameters (void) and any return type: one for initialisation and 42 one for deinitialisation, add 43 AIF_SET_INIT_AND_DEINIT_FUNCS(FuncInitName, FuncDeInitName) to the code, 44 and functions will be automatically called during application startup 45 and shutdown. 46 This is useful for libraries as libraries don't have direct access 47 to the main() function. 48 49 Example: 50 ------------------------------------------------- 51 #include <stdlib.h> 52 #include "autoinit_funcs.h" 53 54 int someVar; 55 void* somePtr; 56 57 void libInit(void) 58 { 59 someVar = 3; 60 // Calling other library functions could be unsafe the as the order 61 // of initialisation of libraries is not strictly defined 62 //somePtr = malloc(100); 63 } 64 65 void libDeinit(void) 66 { 67 // Calling other library functions could be unsafe 68 //free(somePtr); 69 } 70 71 AIF_SET_INIT_AND_DEINIT_FUNCS(libInit,libDeinit); 72 ------------------------------------------------- 73 74 If initialiser or deinitialiser function is not needed, just use 75 an empty function as a placeholder. 76 77 This header should work with GCC, clang, MSVC (2010 or later) and 78 SunPro / Sun Studio / Oracle Solaris Studio / Oracle Developer Studio 79 compiler and other compatible compilers. 80 Supported C and C++ languages; application, static and dynamic (DLL) 81 libraries; non-optimized (Debug) and optimised (Release) compilation 82 and linking. 83 84 Besides the main macro mentioned above, the header defines other helper 85 macros prefixed with AIF_. These macros can be used directly, but they 86 are not designed to be defined externally. 87 88 The header behaviour could be adjusted by defining various AUTOINIT_FUNCS_* 89 macros before including the header. 90 91 For more information see the header code and comments in the code. 92 */ 93 #ifndef AIF_HEADER_INCLUDED 94 #define AIF_HEADER_INCLUDED 1 95 96 /** 97 * The header version number in packed BCD form. 98 * (For example, version 1.9.30-1 would be 0x01093001) 99 */ 100 #define AIF_VERSION 0x02000301 101 102 /* Define AUTOINIT_FUNCS_NO_WARNINGS to disable all custom warnings 103 in this header */ 104 #ifdef AUTOINIT_FUNCS_NO_WARNINGS 105 # ifndef AUTOINIT_FUNCS_NO_WARNINGS_W32_ARCH 106 # define AUTOINIT_FUNCS_NO_WARNINGS_W32_ARCH 1 107 # endif 108 # ifndef AUTOINIT_FUNCS_NO_WARNINGS_SUNPRO_C 109 # define AUTOINIT_FUNCS_NO_WARNINGS_SUNPRO_C 1 110 # endif 111 #endif 112 113 /* If possible - check for supported attributes */ 114 #ifdef __has_attribute 115 # if __has_attribute (constructor) && __has_attribute (destructor) 116 # define AIF_GNUC_ATTR_CONSTR_SUPPORTED 1 117 # else /* ! __has_attribute (constructor) || ! __has_attribute (destructor) */ 118 # define AIF_GNUC_ATTR_CONSTR_NOT_SUPPORTED 1 119 # endif /* ! __has_attribute (constructor) || ! __has_attribute (destructor) */ 120 #endif /* __has_attribute */ 121 122 #if defined(__GNUC__) && __GNUC__ < 2 \ 123 && !defined(AIF_GNUC_ATTR_CONSTR_NOT_SUPPORTED) \ 124 && !defined(AIF_GNUC_ATTR_CONSTR_SUPPORTED) 125 # define AIF_GNUC_ATTR_CONSTR_NOT_SUPPORTED 1 126 #endif 127 128 /* "__has_attribute__ ((constructor))" is supported by GCC, clang and 129 Sun/Oracle compiler starting from version 12.1. */ 130 #if (defined(AIF_GNUC_ATTR_CONSTR_SUPPORTED) \ 131 || defined(__GNUC__) || defined(__clang__) \ 132 || (defined(__SUNPRO_C) && __SUNPRO_C + 0 >= 0x5100)) && \ 133 !defined(AIF_GNUC_ATTR_CONSTR_NOT_SUPPORTED) 134 135 # define AIF_GNUC_SET_INIT_AND_DEINIT(FI, FD) \ 136 void __attribute__ ((constructor)) AIF_GNUC_init_helper_ ## FI (void); \ 137 void __attribute__ ((destructor)) AIF_GNUC_deinit_helper_ ## FD (void); \ 138 void __attribute__ ((constructor)) AIF_GNUC_init_helper_ ## FI (void) \ 139 { (void) (FI) (); } \ 140 void __attribute__ ((destructor)) AIF_GNUC_deinit_helper_ ## FD (void) \ 141 { (void) (FD) (); } \ 142 struct AIF_GNUC_dummy_str_ ## FI {int i;} 143 144 #elif defined(_WIN32) && defined(_MSC_FULL_VER) && _MSC_VER + 0 >= 1600 && \ 145 !defined(__CYGWIN__) 146 147 /* Make sure that your project/sources define: 148 _LIB if building a static library (_LIB is ignored if _CONSOLE is defined); 149 _USRDLL if building DLL-library; 150 not defined both _LIB and _USRDLL if building an application */ 151 152 /* Stringify macros */ 153 # define AIF_INSTRMACRO(a) #a /* Strigify helper */ 154 # define AIF_STRMACRO(a) AIF_INSTRMACRO (a) /* Expand and strigify */ 155 156 /* Concatenate macros */ 157 # define AIF_INCONCAT(a, b) a ## b /* Concatenate helper */ 158 # define AIF_CONCAT(a, b) AIF_INCONCAT (a,b) /* Expand and concatenate */ 159 160 /* Use "C" linkage for variables to simplify symbols decoration */ 161 # ifdef __cplusplus 162 # define AIF_W32_INITVARDECL extern "C" 163 # define AIF_W32_INITHELPERFUNCDECL static 164 # else 165 # define AIF_W32_INITVARDECL extern 166 # define AIF_W32_INITHELPERFUNCDECL static 167 # endif 168 169 /* How variables are decorated by compiler */ 170 # if (defined(_WIN32) || defined(_WIN64)) \ 171 && !defined(_M_IX86) && !defined(_X86_) 172 # if !defined(_M_X64) && !defined(_M_AMD64) && !defined(_x86_64_) \ 173 && !defined(_M_ARM) && !defined(_M_ARM64) 174 # ifndef AUTOINIT_FUNCS_NO_WARNINGS_W32_ARCH 175 # pragma \ 176 message(__FILE__ "(" AIF_STRMACRO(__LINE__) ") : warning AIFW001 : " \ 177 "Untested architecture, linker may fail with unresolved symbols") 178 # endif /* ! AUTOINIT_FUNCS_NO_WARNINGS_W32_ARCH */ 179 # endif /* ! _M_X64 && ! _M_AMD64 && ! _x86_64_ && ! _M_ARM && ! _M_ARM64 */ 180 # define AIF_W32_VARDECORPREFIX 181 # define AIF_W32_DECORVARNAME(v) v 182 # define AIF_W32_VARDECORPREFIXSTR "" 183 # elif defined(_WIN32) && (defined(_M_IX86) || defined(_X86_)) 184 # define AIF_W32_VARDECORPREFIX _ 185 # define AIF_W32_DECORVARNAME(v) _ ## v 186 # define AIF_W32_VARDECORPREFIXSTR "_" 187 # else 188 # error Do not know how to decorate symbols for this architecture 189 # endif 190 191 192 /* Internal variable prefix (can be any) */ 193 # define AIF_W32_INITHELPERVARNAME(f) _aif_init_ptr_ ## f 194 # define AIF_W32_INITHELPERVARNAMEDECORSTR(f) \ 195 AIF_W32_VARDECORPREFIXSTR AIF_STRMACRO (AIF_W32_INITHELPERVARNAME (f)) 196 197 198 /* Sections (segments) for pointers to initialisers */ 199 200 /* Semi-officially suggested section for early initialisers (called before 201 C++ objects initialisers), "void" return type */ 202 # define AIF_W32_SEG_STAT_INIT_EARLY1 ".CRT$XCT" 203 /* Guessed section name for early initialisers (called before 204 C++ objects initialisers, after first initialisers), "void" return type */ 205 # define AIF_W32_SEG_STAT_INIT_EARLY2 ".CRT$XCTa" 206 /* Semi-officially suggested section for late initialisers (called after 207 C++ objects initialisers), "void" return type */ 208 # define AIF_W32_SEG_STAT_INIT_LATE ".CRT$XCV" 209 210 /* Unsafe sections (segments) for pointers to initialisers */ 211 212 /* C++ lib initialisers, "void" return type (reserved by the system!) */ 213 # define AIF_W32_SEG_STAT_INIT_CXX_LIB ".CRT$XCL" 214 /* C++ user initialisers, "void" return type (reserved by the system!) */ 215 # define AIF_W32_SEG_STAT_INIT_CXX_USER ".CRT$XCU" 216 217 /* Declare section (segment), put variable pointing to init function to 218 chosen segment, force linker to always include variable to avoid omitting 219 by optimiser */ 220 /* These initialisation function must be declared as 221 void __cdecl FuncName(void) */ 222 /* Note: "extern" with initialisation value means that variable is declared AND 223 defined. */ 224 # define AIF_W32_INIT_VFPTR_IN_SEG(S, F) \ 225 __pragma(section(S, long, read)) \ 226 __pragma(comment(linker, "/INCLUDE:" \ 227 AIF_W32_INITHELPERVARNAMEDECORSTR (F))) \ 228 AIF_W32_INITVARDECL __declspec(allocate (S)) void \ 229 (__cdecl * AIF_W32_INITHELPERVARNAME (F))(void) = &F 230 231 /* Unsafe sections (segments) for pointers to initialisers with 232 "int" return type */ 233 234 /* C lib initialisers, "int" return type (reserved by the system!). 235 These initialisers are called before others. */ 236 # define AIF_W32_SEG_STAT_INIT_C_LIB ".CRT$XIL" 237 /* C user initialisers, "int" return type (reserved by the system!). 238 These initialisers are called before others. */ 239 # define AIF_W32_SEG_STAT_INIT_C_USER ".CRT$XIU" 240 241 /* Declare section (segment), put variable pointing to init function to 242 chosen segment, force linker to always include variable to avoid omitting 243 by optimiser */ 244 /* These initialisation function must be declared as 245 int __cdecl FuncName(void) */ 246 /* Startup process is aborted if initialiser returns non-zero */ 247 /* Note: "extern" with initialisation value means that variable is declared AND 248 defined. */ 249 # define AIF_W32_INIT_IFPTR_IN_SEG(S, F) \ 250 __pragma(section(S, long, read)) \ 251 __pragma(comment(linker, \ 252 "/INCLUDE:" AIF_W32_INITHELPERVARNAMEDECORSTR (F))) \ 253 AIF_W32_INITVARDECL __declspec(allocate (S)) int \ 254 (__cdecl * AIF_W32_INITHELPERVARNAME (F))(void) = &F 255 256 /* Not recommended / unsafe */ 257 /* "lib" initialisers are called before "user" initialisers */ 258 /* "C" initialisers are called before "C++" initialisers */ 259 # define AIF_W32_REG_STAT_INIT_C_USER(F) \ 260 AIF_W32_FPTR_IN_SEG (AIF_W32_SEG_STAT_INIT_C_USER,F) 261 # define AIF_W32_REG_STAT_INIT_C_LIB(F) \ 262 AIF_W32_FPTR_IN_SEG (AIF_W32_SEG_STAT_INIT_C_LIB,F) 263 # define AIF_W32_REG_STAT_INIT_CXX_USER(F) \ 264 AIF_W32_FPTR_IN_SEG (AIF_W32_SEG_STAT_INIT_CXX_USER,F) 265 # define AIF_W32_REG_STAT_INIT_CXX_LIB(F) \ 266 AIF_W32_FPTR_IN_SEG (AIF_W32_SEG_STAT_INIT_CXX_LIB,F) 267 268 /* Declare macros for different initialisers sections */ 269 270 /* Macro can be used several times to register several initialisers */ 271 /* Once function is registered as initialiser, it will be called automatically 272 during application startup or library loading */ 273 # define AIF_W32_REG_STAT_INIT_EARLY1(F) \ 274 AIF_W32_INIT_VFPTR_IN_SEG (AIF_W32_SEG_STAT_INIT_EARLY1,F) 275 # define AIF_W32_REG_STAT_INIT_EARLY2(F) \ 276 AIF_W32_INIT_VFPTR_IN_SEG (AIF_W32_SEG_STAT_INIT_EARLY2,F) 277 # define AIF_W32_REG_STAT_INIT_LATE(F) \ 278 AIF_W32_INIT_VFPTR_IN_SEG (AIF_W32_SEG_STAT_INIT_LATE,F) 279 280 # ifndef _DLL 281 /* Sections (segments) for pointers to deinitialisers */ 282 283 /* These section are not used when common rutime (CRT, the C library) is used 284 as DLL. In such case only sections in CRT DLL are used for deinitialisation 285 pointers. */ 286 287 /* The section name based on semi-documented deinitialisation procedure, 288 functions called before first C deinitialisers, "void" return type */ 289 # define AIF_W32_SEG_STAT_DEINIT_FIRST ".CRT$XPAa" 290 /* The section name based on semi-documented deinitialisation procedure, 291 functions called after AIF_W32_SEG_STAT_DEINIT_FIRST deinitialisers and 292 before first C deinitialisers, "void" return type */ 293 # define AIF_W32_SEG_STAT_DEINIT_SECOND ".CRT$XPAb" 294 /* The section name based on semi-documented deinitialisation procedure, 295 functions called after AIF_W32_SEG_STAT_DEINIT_SECOND deinitialisers and 296 before first C deinitialisers, "void" return type */ 297 # define AIF_W32_SEG_STAT_DEINIT_THIRD ".CRT$XPAc" 298 299 /* Internal variable prefix (can be any) */ 300 # define AIF_W32_DEINITHELPERVARNAME(f) _aif_deinit_ptr_ ## f 301 # define AIF_W32_DEINITHELPERVARNAMEDECORSTR(f) \ 302 AIF_W32_VARDECORPREFIXSTR AIF_STRMACRO (AIF_W32_DEINITHELPERVARNAME (f)) 303 304 /* The macro to declare section (segment), put variable pointing to deinit 305 function to chosen segment, force linker to always include variable to 306 avoid omitting by optimiser */ 307 /* These deinitialisation function must be declared as 308 void __cdecl FuncName(void) */ 309 /* Note: "extern" with initialisation value means that variable is declared AND 310 defined. */ 311 # define AIF_W32_DEINIT_VFPTR_IN_SEG(S, F) \ 312 __pragma(section(S, long, read)) \ 313 __pragma(comment(linker, "/INCLUDE:" \ 314 AIF_W32_DEINITHELPERVARNAMEDECORSTR (F))) \ 315 AIF_W32_INITVARDECL __declspec(allocate (S)) void \ 316 (__cdecl * AIF_W32_DEINITHELPERVARNAME (F))(void) = &F 317 318 /* Declare macros for different deinitialisers sections */ 319 /* Macro can be used several times to register several deinitialisers */ 320 /* Once function is registered as initialiser, it will be called automatically 321 during application shutdown or library unloading */ 322 # define AIF_W32_REG_STAT_DEINIT_EARLY(F) \ 323 AIF_W32_DEINIT_VFPTR_IN_SEG (AIF_W32_SEG_STAT_DEINIT_FIRST,F) 324 # define AIF_W32_REG_STAT_DEINIT_LATE1(F) \ 325 AIF_W32_DEINIT_VFPTR_IN_SEG (AIF_W32_SEG_STAT_DEINIT_SECOND,F) 326 # define AIF_W32_REG_STAT_DEINIT_LATE2(F) \ 327 AIF_W32_DEINIT_VFPTR_IN_SEG (AIF_W32_SEG_STAT_DEINIT_THIRD,F) 328 329 # endif /* ! _DLL */ 330 331 /* Choose main register macro based on language and program type */ 332 /* Assuming that _LIB or _USRDLL is defined for static or DLL-library */ 333 /* Macro can be used several times to register several initialisers */ 334 /* Once function is registered as initialiser, it will be called automatically 335 during application startup */ 336 /* Define AUTOINIT_FUNCS_FORCE_EARLY_INIT to force register as early 337 initialiser */ 338 /* Define AUTOINIT_FUNCS_FORCE_LATE_INIT to force register as late 339 initialiser */ 340 /* By default C++ static or DLL-library code and any C code and will be 341 registered as early initialiser, while C++ non-library code will be 342 registered as late initialiser */ 343 # if (!defined(__cplusplus) || \ 344 defined(_LIB) || defined(_USRDLL) || \ 345 defined(AUTOINIT_FUNCS_FORCE_EARLY_INIT)) && \ 346 !defined(AUTOINIT_FUNCS_FORCE_LATE_INIT) 347 /* Use early initialiser and late deinitialiser */ 348 # if defined(_LIB) || defined(_USRDLL) 349 /* Static or DLL library */ 350 # define AIF_W32_REGISTER_STAT_INIT(F) AIF_W32_REG_STAT_INIT_EARLY1 (F) 351 # ifdef AIF_W32_REG_STAT_DEINIT_LATE2 352 # define AIF_W32_REGISTER_STAT_DEINIT(F) \ 353 AIF_W32_REG_STAT_DEINIT_LATE2 (F) 354 # endif 355 # else 356 /* Application code */ 357 # define AIF_W32_REGISTER_STAT_INIT(F) AIF_W32_REG_STAT_INIT_EARLY2 (F) 358 # ifdef AIF_W32_REG_STAT_DEINIT_LATE1 359 # define AIF_W32_REGISTER_STAT_DEINIT(F) \ 360 AIF_W32_REG_STAT_DEINIT_LATE1 (F) 361 # endif 362 # endif 363 # else 364 /* Use late initialiser and early deinitialiser */ 365 # define AIF_W32_REGISTER_STAT_INIT(F) AIF_W32_REG_STAT_INIT_LATE (F) 366 # ifdef AIF_W32_REG_STAT_DEINIT_EARLY 367 # define AIF_W32_REGISTER_STAT_DEINIT(F) \ 368 AIF_W32_REG_STAT_DEINIT_EARLY (F) 369 # endif 370 # endif 371 372 373 /* Static deinit registration on W32 could be risky as it works only 374 if CRT is used as static lib (not as DLL) and relies on correct 375 definition of "_DLL" macro by build system. */ 376 /* If "_DLL" macro is correctly defined, static deinitialiser registration 377 can be enabled by defining AUTOINIT_FUNCS_ALLOW_W32_STAT_DEINIT macro. 378 If it is used, it can save from including an extra header. */ 379 # if defined(AIF_W32_REGISTER_STAT_DEINIT) \ 380 && defined(AUTOINIT_FUNCS_ALLOW_W32_STAT_DEINIT) 381 # define AIF_W32_SET_STAT_INIT_AND_DEINIT(FI, FD) \ 382 AIF_W32_INITHELPERFUNCDECL void \ 383 __cdecl AIF_W32_stat_init_helper_ ## FI (void); \ 384 AIF_W32_INITHELPERFUNCDECL void \ 385 __cdecl AIF_W32_stat_deinit_helper_ ## FD (void); \ 386 AIF_W32_INITHELPERFUNCDECL void \ 387 __cdecl AIF_W32_stat_init_helper_ ## FI (void) \ 388 { (void) (FI) (); } \ 389 AIF_W32_INITHELPERFUNCDECL void \ 390 __cdecl AIF_W32_stat_deinit_helper_ ## FD (void) \ 391 { (void) (FD) (); } \ 392 AIF_W32_REGISTER_STAT_INIT (AIF_W32_stat_init_helper_ ## FI); \ 393 AIF_W32_REGISTER_STAT_DEINIT (AIF_W32_stat_deinit_helper_ ## FD) 394 # else 395 396 /* Note: 'atexit()' is just a wrapper for '_onexit()' on W32 */ 397 # include <stdlib.h> /* required for _onexit() */ 398 399 # define AIF_W32_SET_STAT_INIT_AND_DEINIT(FI, FD) \ 400 AIF_W32_INITHELPERFUNCDECL void \ 401 __cdecl AIF_W32_stat_init_helper_ ## FI (void); \ 402 AIF_W32_INITHELPERFUNCDECL int \ 403 __cdecl AIF_W32_stat_deinit_helper_ ## FD (void); \ 404 AIF_W32_INITHELPERFUNCDECL void \ 405 __cdecl AIF_W32_stat_init_helper_ ## FI (void) \ 406 { (void) (FI) (); \ 407 _onexit (&AIF_W32_stat_deinit_helper_ ## FD); } \ 408 AIF_W32_INITHELPERFUNCDECL int \ 409 __cdecl AIF_W32_stat_deinit_helper_ ## FD (void) \ 410 { (void) (FD) (); return ! 0; } \ 411 AIF_W32_REGISTER_STAT_INIT (AIF_W32_stat_init_helper_ ## FI) 412 # endif 413 414 #endif /* _WIN32 && _MSC_VER + 0 >= 1600 && ! _GNUC_ATTR_CONSTR_SUPPORTED */ 415 416 417 #if defined(_WIN32) && !defined(__CYGWIN__) && \ 418 (defined(_USRDLL) || defined(DLL_EXPORT)) 419 420 # if defined(__MINGW32__) || defined(__MINGW64__) 421 /* The minimal portable set of the headers to pull in the definitions of "BOOL", 422 "WINAPI", "HINSTANCE", "DWORD" and "LPVOID" */ 423 /* Thi minimal set does not work with MS headers as they depend on some vital 424 macros defined only in the "windows.h" header only */ 425 # include <windef.h> 426 # include <winnt.h> 427 # else 428 # ifndef WIN32_LEAN_AND_MEAN 429 # define WIN32_LEAN_AND_MEAN 1 430 # endif 431 # include <windows.h> 432 # endif 433 434 # ifdef DLL_PROCESS_ATTACH 435 # define AIF_W32_DLL_PROCESS_ATTACH DLL_PROCESS_ATTACH 436 # else 437 # define AIF_W32_DLL_PROCESS_ATTACH 1 438 # endif 439 # if defined(DLL_PROCESS_DETACH) 440 # define AIF_W32_DLL_PROCESS_DETACH DLL_PROCESS_DETACH 441 # else 442 # define AIF_W32_DLL_PROCESS_DETACH 0 443 # endif 444 445 /* When process is terminating, DLL should not perform a cleanup, leaving 446 allocated resources to be cleaned by the system. This is because some 447 threads may be explicitly terminated without proper cleanup, and some 448 system resources, including process heap, could be in inconsistent state. 449 Define AUTOINIT_FUNCS_USE_UNSAFE_DLL_DEINIT to enable calling of deinit 450 function such situations. 451 Note: if AUTOINIT_FUNCS_USE_UNSAFE_DLL_DEINIT is defined and the DLL is 452 delay-loaded, then both the initialiser and the deinitialiser could be 453 called late (or last), breaking requirement for calling deinitialisers in 454 reverse order of initialisers. */ 455 # ifndef AUTOINIT_FUNCS_USE_UNSAFE_DLL_DEINIT 456 # define AIF_W32_IS_DLL_DEINIT_SAFE(pReserved) (NULL == (pReserved)) 457 # else 458 # define AIF_W32_IS_DLL_DEINIT_SAFE(pReserved) TRUE 459 # endif 460 461 /* If DllMain is already present in user's code, 462 define AUTOINIT_FUNCS_CALL_USR_DLLMAIN and 463 rename user's DllMain to usr_DllMain. 464 The usr_DllMain() must be declared (or full defined) before using the macro 465 for setting initialiser and deinitialiser. Alternatively, if usr_DllMain() 466 is another file (or after the macro), define macro 467 AUTOINIT_FUNCS_DECLARE_USR_DLLMAIN to enable automatic declaration of this 468 function. 469 Define AUTOINIT_FUNCS_USR_DLLMAIN_NAME to user function name if usr_DllMain 470 is not suitable. */ 471 # ifndef AUTOINIT_FUNCS_CALL_USR_DLLMAIN 472 # define AIF_W32_CALL_USER_DLLMAIN(h, r, p) TRUE 473 # else /* AUTOINIT_FUNCS_CALL_USR_DLLMAIN */ 474 # ifndef AUTOINIT_FUNCS_USR_DLLMAIN_NAME 475 # define AIF_W32_USR_DLLMAIN_NAME usr_DllMain 476 # else 477 # define AIF_W32_USR_DLLMAIN_NAME AUTOINIT_FUNCS_USR_DLLMAIN_NAME 478 # endif 479 # define AIF_W32_CALL_USER_DLLMAIN(h, r, p) \ 480 AIF_W32_USR_DLLMAIN_NAME ((h),(r),(p)) 481 # ifdef AUTOINIT_FUNCS_DECLARE_USR_DLLMAIN 482 # define AIF_DECL_USR_DLLMAIN \ 483 BOOL WINAPI AIF_W32_USR_DLLMAIN_NAME (HINSTANCE hinst, DWORD reason, \ 484 LPVOID pReserved); 485 # endif 486 # endif /* AUTOINIT_FUNCS_CALL_USR_DLLMAIN */ 487 488 # ifndef AIF_DECL_USR_DLLMAIN 489 # define AIF_DECL_USR_DLLMAIN /* empty */ 490 # endif 491 492 # define AIF_W32_SET_DLL_INIT_AND_DEINIT(FI, FD) \ 493 BOOL WINAPI DllMain (HINSTANCE hinst, DWORD reason, LPVOID pReserved); \ 494 AIF_DECL_USR_DLLMAIN \ 495 BOOL WINAPI DllMain (HINSTANCE hinst, DWORD reason, LPVOID pReserved) \ 496 { BOOL aif_ret; (void) hinst; \ 497 if (AIF_W32_DLL_PROCESS_ATTACH == reason) { \ 498 (void) (FI) (); \ 499 aif_ret = AIF_W32_CALL_USER_DLLMAIN (hinst, reason, pReserved); \ 500 if (! aif_ret && NULL != pReserved) { (void) (FD) (); } } \ 501 else if (AIF_W32_DLL_PROCESS_DETACH == reason) { \ 502 aif_ret = AIF_W32_CALL_USER_DLLMAIN (hinst, reason, pReserved); \ 503 if (AIF_W32_IS_DLL_DEINIT_SAFE (pReserved)) { (void) (FD) (); } } \ 504 else aif_ret = AIF_W32_CALL_USER_DLLMAIN (hinst, reason, pReserved); \ 505 return aif_ret; \ 506 } struct AIF_W32_dummy_strc_ ## FI {int i;} 507 #endif /* _WIN32 && ! __CYGWIN__ && (_USRDLL || DLL_EXPORT) */ 508 509 510 /* Define AUTOINIT_FUNCS_FORCE_STATIC_REG if you want to set main macro 511 AIF_SET_INIT_AND_DEINIT_FUNCS to static version even if building a DLL. 512 Static registration works for DLL too, but less precise and flexible. */ 513 514 #if defined(AIF_W32_SET_DLL_INIT_AND_DEINIT) \ 515 && !(defined(AUTOINIT_FUNCS_PREFER_STATIC_REG) \ 516 && (defined(AIF_GNUC_SET_INIT_AND_DEINIT) \ 517 || defined(AIF_W32_SET_STAT_INIT_AND_DEINIT))) 518 519 # define AIF_SET_INIT_AND_DEINIT_FUNCS(FI, FD) \ 520 AIF_W32_SET_DLL_INIT_AND_DEINIT (FI,FD) 521 /* Indicate that automatic initialisers/deinitialisers are supported */ 522 # define AIF_AUTOINIT_FUNCS_ARE_SUPPORTED 1 523 524 #elif defined(AIF_GNUC_SET_INIT_AND_DEINIT) 525 526 # define AIF_SET_INIT_AND_DEINIT_FUNCS(FI, FD) \ 527 AIF_GNUC_SET_INIT_AND_DEINIT (FI,FD) 528 /* Indicate that automatic initialisers/deinitialisers are supported */ 529 # define AIF_AUTOINIT_FUNCS_ARE_SUPPORTED 1 530 531 #elif defined(AIF_W32_SET_STAT_INIT_AND_DEINIT) 532 533 # define AIF_SET_INIT_AND_DEINIT_FUNCS(FI, FD) \ 534 AIF_W32_SET_STAT_INIT_AND_DEINIT (FI,FD) 535 /* Indicate that automatic initialisers/deinitialisers are supported */ 536 # define AIF_AUTOINIT_FUNCS_ARE_SUPPORTED 1 537 538 #else 539 540 /* Define AUTOINIT_FUNCS_EMIT_ERROR_IF_NOT_SUPPORTED before inclusion of 541 this header to abort compilation if automatic initialisers/deinitialisers 542 are not supported */ 543 # ifdef AUTOINIT_FUNCS_EMIT_ERROR_IF_NOT_SUPPORTED 544 # error User-defined initialiser and deinitialiser functions not supported 545 # endif /* AUTOINIT_FUNCS_EMIT_ERROR_IF_NOT_SUPPORTED */ 546 547 # if defined(__SUNPRO_C) && (defined(sun) || defined(__sun)) \ 548 && (defined(__SVR4) || defined(__svr4__)) 549 /* "#parama init(func_name)" can be used. "func_name" must be declared. 550 The form is "void func_name(void)". */ 551 # define AIF_PRAGMA_INIT_SUPPORTED 1 552 /* "#parama fini(func_name)" can be used. "func_name" must be declared. 553 The form is "void func_name(void)". */ 554 # define AIF_PRAGMA_FINI_SUPPORTED 1 555 # if !defined(AUTOINIT_FUNCS_NO_WARNINGS_SUNPRO_C) 556 # warning Compiler supports "#pragma init(func)" and "#pragma fini(func)" 557 # warning Use "pragma" to set initialiser and deinitialiser functions 558 # endif 559 # endif 560 561 /* "Not supported" implementation */ 562 # define AIF_SET_INIT_AND_DEINIT_FUNCS(FI, FD) /* No-op */ 563 /* Indicate that automatic initialisers/deinitialisers are not supported */ 564 # define AIF_AUTOINIT_FUNCS_ARE_NOT_SUPPORTED 1 565 566 #endif 567 #endif /* !AIF_HEADER_INCLUDED */