autoinit_funcs.h (25364B)
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 0x02000300 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 message(__FILE__ "(" AIF_STRMACRO(__LINE__) ") : warning AIFW001 : " \ 176 "Untested architecture, linker may fail with unresolved symbols") 177 # endif /* ! AUTOINIT_FUNCS_NO_WARNINGS_W32_ARCH */ 178 # endif /* ! _M_X64 && ! _M_AMD64 && ! _x86_64_ && ! _M_ARM && ! _M_ARM64 */ 179 # define AIF_W32_VARDECORPREFIX 180 # define AIF_W32_DECORVARNAME(v) v 181 # define AIF_W32_VARDECORPREFIXSTR "" 182 # elif defined(_WIN32) && (defined(_M_IX86) || defined(_X86_)) 183 # define AIF_W32_VARDECORPREFIX _ 184 # define AIF_W32_DECORVARNAME(v) _ ## v 185 # define AIF_W32_VARDECORPREFIXSTR "_" 186 # else 187 #error Do not know how to decorate symbols for this architecture 188 # endif 189 190 191 /* Internal variable prefix (can be any) */ 192 # define AIF_W32_INITHELPERVARNAME(f) _aif_init_ptr_ ## f 193 # define AIF_W32_INITHELPERVARNAMEDECORSTR(f) \ 194 AIF_W32_VARDECORPREFIXSTR AIF_STRMACRO (AIF_W32_INITHELPERVARNAME (f)) 195 196 197 /* Sections (segments) for pointers to initialisers */ 198 199 /* Semi-officially suggested section for early initialisers (called before 200 C++ objects initialisers), "void" return type */ 201 # define AIF_W32_SEG_STAT_INIT_EARLY1 ".CRT$XCT" 202 /* Guessed section name for early initialisers (called before 203 C++ objects initialisers, after first initialisers), "void" return type */ 204 # define AIF_W32_SEG_STAT_INIT_EARLY2 ".CRT$XCTa" 205 /* Semi-officially suggested section for late initialisers (called after 206 C++ objects initialisers), "void" return type */ 207 # define AIF_W32_SEG_STAT_INIT_LATE ".CRT$XCV" 208 209 /* Unsafe sections (segments) for pointers to initialisers */ 210 211 /* C++ lib initialisers, "void" return type (reserved by the system!) */ 212 # define AIF_W32_SEG_STAT_INIT_CXX_LIB ".CRT$XCL" 213 /* C++ user initialisers, "void" return type (reserved by the system!) */ 214 # define AIF_W32_SEG_STAT_INIT_CXX_USER ".CRT$XCU" 215 216 /* Declare section (segment), put variable pointing to init function to 217 chosen segment, force linker to always include variable to avoid omitting 218 by optimiser */ 219 /* These initialisation function must be declared as 220 void __cdecl FuncName(void) */ 221 /* Note: "extern" with initialisation value means that variable is declared AND 222 defined. */ 223 # define AIF_W32_INIT_VFPTR_IN_SEG(S,F) \ 224 __pragma(section(S, long, read)) \ 225 __pragma(comment(linker, "/INCLUDE:" \ 226 AIF_W32_INITHELPERVARNAMEDECORSTR (F))) \ 227 AIF_W32_INITVARDECL __declspec(allocate (S)) void \ 228 (__cdecl * AIF_W32_INITHELPERVARNAME (F))(void) = &F 229 230 /* Unsafe sections (segments) for pointers to initialisers with 231 "int" return type */ 232 233 /* C lib initialisers, "int" return type (reserved by the system!). 234 These initialisers are called before others. */ 235 # define AIF_W32_SEG_STAT_INIT_C_LIB ".CRT$XIL" 236 /* C user initialisers, "int" return type (reserved by the system!). 237 These initialisers are called before others. */ 238 # define AIF_W32_SEG_STAT_INIT_C_USER ".CRT$XIU" 239 240 /* Declare section (segment), put variable pointing to init function to 241 chosen segment, force linker to always include variable to avoid omitting 242 by optimiser */ 243 /* These initialisation function must be declared as 244 int __cdecl FuncName(void) */ 245 /* Startup process is aborted if initialiser returns non-zero */ 246 /* Note: "extern" with initialisation value means that variable is declared AND 247 defined. */ 248 # define AIF_W32_INIT_IFPTR_IN_SEG(S,F) \ 249 __pragma(section(S, long, read)) \ 250 __pragma(comment(linker, \ 251 "/INCLUDE:" AIF_W32_INITHELPERVARNAMEDECORSTR (F))) \ 252 AIF_W32_INITVARDECL __declspec(allocate (S)) int \ 253 (__cdecl * AIF_W32_INITHELPERVARNAME (F))(void) = &F 254 255 /* Not recommended / unsafe */ 256 /* "lib" initialisers are called before "user" initialisers */ 257 /* "C" initialisers are called before "C++" initialisers */ 258 # define AIF_W32_REG_STAT_INIT_C_USER(F) \ 259 AIF_W32_FPTR_IN_SEG (AIF_W32_SEG_STAT_INIT_C_USER,F) 260 # define AIF_W32_REG_STAT_INIT_C_LIB(F) \ 261 AIF_W32_FPTR_IN_SEG (AIF_W32_SEG_STAT_INIT_C_LIB,F) 262 # define AIF_W32_REG_STAT_INIT_CXX_USER(F) \ 263 AIF_W32_FPTR_IN_SEG (AIF_W32_SEG_STAT_INIT_CXX_USER,F) 264 # define AIF_W32_REG_STAT_INIT_CXX_LIB(F) \ 265 AIF_W32_FPTR_IN_SEG (AIF_W32_SEG_STAT_INIT_CXX_LIB,F) 266 267 /* Declare macros for different initialisers sections */ 268 269 /* Macro can be used several times to register several initialisers */ 270 /* Once function is registered as initialiser, it will be called automatically 271 during application startup or library loading */ 272 # define AIF_W32_REG_STAT_INIT_EARLY1(F) \ 273 AIF_W32_INIT_VFPTR_IN_SEG (AIF_W32_SEG_STAT_INIT_EARLY1,F) 274 # define AIF_W32_REG_STAT_INIT_EARLY2(F) \ 275 AIF_W32_INIT_VFPTR_IN_SEG (AIF_W32_SEG_STAT_INIT_EARLY2,F) 276 # define AIF_W32_REG_STAT_INIT_LATE(F) \ 277 AIF_W32_INIT_VFPTR_IN_SEG (AIF_W32_SEG_STAT_INIT_LATE,F) 278 279 # ifndef _DLL 280 /* Sections (segments) for pointers to deinitialisers */ 281 282 /* These section are not used when common rutime (CRT, the C library) is used 283 as DLL. In such case only sections in CRT DLL are used for deinitialisation 284 pointers. */ 285 286 /* The section name based on semi-documented deinitialisation procedure, 287 functions called before first C deinitialisers, "void" return type */ 288 # define AIF_W32_SEG_STAT_DEINIT_FIRST ".CRT$XPAa" 289 /* The section name based on semi-documented deinitialisation procedure, 290 functions called after AIF_W32_SEG_STAT_DEINIT_FIRST deinitialisers and 291 before first C deinitialisers, "void" return type */ 292 # define AIF_W32_SEG_STAT_DEINIT_SECOND ".CRT$XPAb" 293 /* The section name based on semi-documented deinitialisation procedure, 294 functions called after AIF_W32_SEG_STAT_DEINIT_SECOND deinitialisers and 295 before first C deinitialisers, "void" return type */ 296 # define AIF_W32_SEG_STAT_DEINIT_THIRD ".CRT$XPAc" 297 298 /* Internal variable prefix (can be any) */ 299 # define AIF_W32_DEINITHELPERVARNAME(f) _aif_deinit_ptr_ ## f 300 # define AIF_W32_DEINITHELPERVARNAMEDECORSTR(f) \ 301 AIF_W32_VARDECORPREFIXSTR AIF_STRMACRO (AIF_W32_DEINITHELPERVARNAME (f)) 302 303 /* The macro to declare section (segment), put variable pointing to deinit 304 function to chosen segment, force linker to always include variable to 305 avoid omitting by optimiser */ 306 /* These deinitialisation function must be declared as 307 void __cdecl FuncName(void) */ 308 /* Note: "extern" with initialisation value means that variable is declared AND 309 defined. */ 310 # define AIF_W32_DEINIT_VFPTR_IN_SEG(S,F) \ 311 __pragma(section(S, long, read)) \ 312 __pragma(comment(linker, "/INCLUDE:" \ 313 AIF_W32_DEINITHELPERVARNAMEDECORSTR (F))) \ 314 AIF_W32_INITVARDECL __declspec(allocate (S)) void \ 315 (__cdecl * AIF_W32_DEINITHELPERVARNAME (F))(void) = &F 316 317 /* Declare macros for different deinitialisers sections */ 318 /* Macro can be used several times to register several deinitialisers */ 319 /* Once function is registered as initialiser, it will be called automatically 320 during application shutdown or library unloading */ 321 # define AIF_W32_REG_STAT_DEINIT_EARLY(F) \ 322 AIF_W32_DEINIT_VFPTR_IN_SEG (AIF_W32_SEG_STAT_DEINIT_FIRST,F) 323 # define AIF_W32_REG_STAT_DEINIT_LATE1(F) \ 324 AIF_W32_DEINIT_VFPTR_IN_SEG (AIF_W32_SEG_STAT_DEINIT_SECOND,F) 325 # define AIF_W32_REG_STAT_DEINIT_LATE2(F) \ 326 AIF_W32_DEINIT_VFPTR_IN_SEG (AIF_W32_SEG_STAT_DEINIT_THIRD,F) 327 328 # endif /* ! _DLL */ 329 330 /* Choose main register macro based on language and program type */ 331 /* Assuming that _LIB or _USRDLL is defined for static or DLL-library */ 332 /* Macro can be used several times to register several initialisers */ 333 /* Once function is registered as initialiser, it will be called automatically 334 during application startup */ 335 /* Define AUTOINIT_FUNCS_FORCE_EARLY_INIT to force register as early 336 initialiser */ 337 /* Define AUTOINIT_FUNCS_FORCE_LATE_INIT to force register as late 338 initialiser */ 339 /* By default C++ static or DLL-library code and any C code and will be 340 registered as early initialiser, while C++ non-library code will be 341 registered as late initialiser */ 342 # if (! defined(__cplusplus) || \ 343 defined(_LIB) || defined(_USRDLL) || \ 344 defined(AUTOINIT_FUNCS_FORCE_EARLY_INIT)) && \ 345 ! defined(AUTOINIT_FUNCS_FORCE_LATE_INIT) 346 /* Use early initialiser and late deinitialiser */ 347 # if defined(_LIB) || defined(_USRDLL) 348 /* Static or DLL library */ 349 # define AIF_W32_REGISTER_STAT_INIT(F) AIF_W32_REG_STAT_INIT_EARLY1 (F) 350 # ifdef AIF_W32_REG_STAT_DEINIT_LATE2 351 # define AIF_W32_REGISTER_STAT_DEINIT(F) \ 352 AIF_W32_REG_STAT_DEINIT_LATE2 (F) 353 # endif 354 # else 355 /* Application code */ 356 # define AIF_W32_REGISTER_STAT_INIT(F) AIF_W32_REG_STAT_INIT_EARLY2 (F) 357 # ifdef AIF_W32_REG_STAT_DEINIT_LATE1 358 # define AIF_W32_REGISTER_STAT_DEINIT(F) \ 359 AIF_W32_REG_STAT_DEINIT_LATE1 (F) 360 # endif 361 # endif 362 # else 363 /* Use late initialiser and early deinitialiser */ 364 # define AIF_W32_REGISTER_STAT_INIT(F) AIF_W32_REG_STAT_INIT_LATE (F) 365 # ifdef AIF_W32_REG_STAT_DEINIT_EARLY 366 # define AIF_W32_REGISTER_STAT_DEINIT(F) \ 367 AIF_W32_REG_STAT_DEINIT_EARLY (F) 368 # endif 369 # endif 370 371 372 /* Static deinit registration on W32 could be risky as it works only 373 if CRT is used as static lib (not as DLL) and relies on correct 374 definition of "_DLL" macro by build system. */ 375 /* If "_DLL" macro is correctly defined, static deinitialiser registration 376 can be enabled by defining AUTOINIT_FUNCS_ALLOW_W32_STAT_DEINIT macro. 377 If it is used, it can save from including an extra header. */ 378 # if defined(AIF_W32_REGISTER_STAT_DEINIT) \ 379 && defined(AUTOINIT_FUNCS_ALLOW_W32_STAT_DEINIT) 380 # define AIF_W32_SET_STAT_INIT_AND_DEINIT(FI,FD) \ 381 AIF_W32_INITHELPERFUNCDECL void \ 382 __cdecl AIF_W32_stat_init_helper_ ## FI (void); \ 383 AIF_W32_INITHELPERFUNCDECL void \ 384 __cdecl AIF_W32_stat_deinit_helper_ ## FD (void); \ 385 AIF_W32_INITHELPERFUNCDECL void \ 386 __cdecl AIF_W32_stat_init_helper_ ## FI (void) \ 387 { (void) (FI) (); } \ 388 AIF_W32_INITHELPERFUNCDECL void \ 389 __cdecl AIF_W32_stat_deinit_helper_ ## FD (void) \ 390 { (void) (FD) (); } \ 391 AIF_W32_REGISTER_STAT_INIT (AIF_W32_stat_init_helper_ ## FI); \ 392 AIF_W32_REGISTER_STAT_DEINIT (AIF_W32_stat_deinit_helper_ ## FD) 393 # else 394 395 /* Note: 'atexit()' is just a wrapper for '_onexit()' on W32 */ 396 # include <stdlib.h> /* required for _onexit() */ 397 398 # define AIF_W32_SET_STAT_INIT_AND_DEINIT(FI,FD) \ 399 AIF_W32_INITHELPERFUNCDECL void \ 400 __cdecl AIF_W32_stat_init_helper_ ## FI (void); \ 401 AIF_W32_INITHELPERFUNCDECL int \ 402 __cdecl AIF_W32_stat_deinit_helper_ ## FD (void); \ 403 AIF_W32_INITHELPERFUNCDECL void \ 404 __cdecl AIF_W32_stat_init_helper_ ## FI (void) \ 405 { (void) (FI) (); \ 406 _onexit (&AIF_W32_stat_deinit_helper_ ## FD); } \ 407 AIF_W32_INITHELPERFUNCDECL int \ 408 __cdecl AIF_W32_stat_deinit_helper_ ## FD (void) \ 409 { (void) (FD) (); return ! 0; } \ 410 AIF_W32_REGISTER_STAT_INIT (AIF_W32_stat_init_helper_ ## FI) 411 # endif 412 413 #endif /* _WIN32 && _MSC_VER + 0 >= 1600 && ! _GNUC_ATTR_CONSTR_SUPPORTED */ 414 415 416 #if defined(_WIN32) && ! defined(__CYGWIN__) && \ 417 (defined(_USRDLL) || defined(DLL_EXPORT)) 418 419 # if defined(__MINGW32__) || defined(__MINGW64__) 420 /* The minimal portable set of the headers to pull in the definitions of "BOOL", 421 "WINAPI", "HINSTANCE", "DWORD" and "LPVOID" */ 422 /* Thi minimal set does not work with MS headers as they depend on some vital 423 macros defined only in the "windows.h" header only */ 424 # include <windef.h> 425 # include <winnt.h> 426 # else 427 # ifndef WIN32_LEAN_AND_MEAN 428 # define WIN32_LEAN_AND_MEAN 1 429 # endif 430 # include <windows.h> 431 # endif 432 433 # ifdef DLL_PROCESS_ATTACH 434 # define AIF_W32_DLL_PROCESS_ATTACH DLL_PROCESS_ATTACH 435 # else 436 # define AIF_W32_DLL_PROCESS_ATTACH 1 437 # endif 438 # if defined(DLL_PROCESS_DETACH) 439 # define AIF_W32_DLL_PROCESS_DETACH DLL_PROCESS_DETACH 440 # else 441 # define AIF_W32_DLL_PROCESS_DETACH 0 442 # endif 443 444 /* When process is terminating, DLL should not perform a cleanup, leaving 445 allocated resources to be cleaned by the system. This is because some 446 threads may be explicitly terminated without proper cleanup, and some 447 system resources, including process heap, could be in inconsistent state. 448 Define AUTOINIT_FUNCS_USE_UNSAFE_DLL_DEINIT to enable calling of deinit 449 function such situations. 450 Note: if AUTOINIT_FUNCS_USE_UNSAFE_DLL_DEINIT is defined and the DLL is 451 delay-loaded, then both the initialiser and the deinitialiser could be 452 called late (or last), breaking requirement for calling deinitialisers in 453 reverse order of initialisers. */ 454 # ifndef AUTOINIT_FUNCS_USE_UNSAFE_DLL_DEINIT 455 # define AIF_W32_IS_DLL_DEINIT_SAFE(pReserved) (NULL == (pReserved)) 456 # else 457 # define AIF_W32_IS_DLL_DEINIT_SAFE(pReserved) TRUE 458 # endif 459 460 /* If DllMain is already present in user's code, 461 define AUTOINIT_FUNCS_CALL_USR_DLLMAIN and 462 rename user's DllMain to usr_DllMain. 463 The usr_DllMain() must be declared (or full defined) before using the macro 464 for setting initialiser and deinitialiser. Alternatively, if usr_DllMain() 465 is another file (or after the macro), define macro 466 AUTOINIT_FUNCS_DECLARE_USR_DLLMAIN to enable automatic declaration of this 467 function. 468 Define AUTOINIT_FUNCS_USR_DLLMAIN_NAME to user function name if usr_DllMain 469 is not suitable. */ 470 # ifndef AUTOINIT_FUNCS_CALL_USR_DLLMAIN 471 # define AIF_W32_CALL_USER_DLLMAIN(h,r,p) TRUE 472 # else /* AUTOINIT_FUNCS_CALL_USR_DLLMAIN */ 473 # ifndef AUTOINIT_FUNCS_USR_DLLMAIN_NAME 474 # define AIF_W32_USR_DLLMAIN_NAME usr_DllMain 475 # else 476 # define AIF_W32_USR_DLLMAIN_NAME AUTOINIT_FUNCS_USR_DLLMAIN_NAME 477 # endif 478 # define AIF_W32_CALL_USER_DLLMAIN(h,r,p) \ 479 AIF_W32_USR_DLLMAIN_NAME ((h),(r),(p)) 480 # ifdef AUTOINIT_FUNCS_DECLARE_USR_DLLMAIN 481 # define AIF_DECL_USR_DLLMAIN \ 482 BOOL WINAPI AIF_W32_USR_DLLMAIN_NAME (HINSTANCE hinst, DWORD reason, \ 483 LPVOID pReserved); 484 # endif 485 # endif /* AUTOINIT_FUNCS_CALL_USR_DLLMAIN */ 486 487 # ifndef AIF_DECL_USR_DLLMAIN 488 # define AIF_DECL_USR_DLLMAIN /* empty */ 489 # endif 490 491 # define AIF_W32_SET_DLL_INIT_AND_DEINIT(FI,FD) \ 492 BOOL WINAPI DllMain (HINSTANCE hinst, DWORD reason, LPVOID pReserved); \ 493 AIF_DECL_USR_DLLMAIN \ 494 BOOL WINAPI DllMain (HINSTANCE hinst, DWORD reason, LPVOID pReserved) \ 495 { BOOL aif_ret; (void) hinst; \ 496 if (AIF_W32_DLL_PROCESS_ATTACH == reason) { \ 497 (void) (FI) (); \ 498 aif_ret = AIF_W32_CALL_USER_DLLMAIN (hinst, reason, pReserved); \ 499 if (! aif_ret && NULL != pReserved) { (void) (FD) (); } } \ 500 else if (AIF_W32_DLL_PROCESS_DETACH == reason) { \ 501 aif_ret = AIF_W32_CALL_USER_DLLMAIN (hinst, reason, pReserved); \ 502 if (AIF_W32_IS_DLL_DEINIT_SAFE (pReserved)) { (void) (FD) (); } } \ 503 else aif_ret = AIF_W32_CALL_USER_DLLMAIN (hinst, reason, pReserved); \ 504 return aif_ret; \ 505 } struct AIF_W32_dummy_strc_ ## FI {int i;} 506 #endif /* _WIN32 && ! __CYGWIN__ && (_USRDLL || DLL_EXPORT) */ 507 508 509 /* Define AUTOINIT_FUNCS_FORCE_STATIC_REG if you want to set main macro 510 AIF_SET_INIT_AND_DEINIT_FUNCS to static version even if building a DLL. 511 Static registration works for DLL too, but less precise and flexible. */ 512 513 #if defined(AIF_W32_SET_DLL_INIT_AND_DEINIT) \ 514 && ! (defined(AUTOINIT_FUNCS_PREFER_STATIC_REG) \ 515 && (defined(AIF_GNUC_SET_INIT_AND_DEINIT) \ 516 || defined(AIF_W32_SET_STAT_INIT_AND_DEINIT))) 517 518 # define AIF_SET_INIT_AND_DEINIT_FUNCS(FI,FD) \ 519 AIF_W32_SET_DLL_INIT_AND_DEINIT (FI,FD) 520 /* Indicate that automatic initialisers/deinitialisers are supported */ 521 # define AIF_AUTOINIT_FUNCS_ARE_SUPPORTED 1 522 523 #elif defined(AIF_GNUC_SET_INIT_AND_DEINIT) 524 525 # define AIF_SET_INIT_AND_DEINIT_FUNCS(FI,FD) \ 526 AIF_GNUC_SET_INIT_AND_DEINIT (FI,FD) 527 /* Indicate that automatic initialisers/deinitialisers are supported */ 528 # define AIF_AUTOINIT_FUNCS_ARE_SUPPORTED 1 529 530 #elif defined(AIF_W32_SET_STAT_INIT_AND_DEINIT) 531 532 # define AIF_SET_INIT_AND_DEINIT_FUNCS(FI,FD) \ 533 AIF_W32_SET_STAT_INIT_AND_DEINIT (FI,FD) 534 /* Indicate that automatic initialisers/deinitialisers are supported */ 535 # define AIF_AUTOINIT_FUNCS_ARE_SUPPORTED 1 536 537 #else 538 539 /* Define AUTOINIT_FUNCS_EMIT_ERROR_IF_NOT_SUPPORTED before inclusion of 540 this header to abort compilation if automatic initialisers/deinitialisers 541 are not supported */ 542 # ifdef AUTOINIT_FUNCS_EMIT_ERROR_IF_NOT_SUPPORTED 543 #error User-defined initialiser and deinitialiser functions are not supported 544 # endif /* AUTOINIT_FUNCS_EMIT_ERROR_IF_NOT_SUPPORTED */ 545 546 # if defined(__SUNPRO_C) && (defined(sun) || defined(__sun)) \ 547 && (defined(__SVR4) || defined(__svr4__)) 548 /* "#parama init(func_name)" can be used. "func_name" must be declared. 549 The form is "void func_name(void)". */ 550 # define AIF_PRAGMA_INIT_SUPPORTED 1 551 /* "#parama fini(func_name)" can be used. "func_name" must be declared. 552 The form is "void func_name(void)". */ 553 # define AIF_PRAGMA_FINI_SUPPORTED 1 554 # if ! defined(AUTOINIT_FUNCS_NO_WARNINGS_SUNPRO_C) 555 #warning The compiler supports "#pragma init(func1)" and "#pragma fini(func2)" 556 #warning Use "pragma" to set initialiser and deinitialiser functions 557 # endif 558 # endif 559 560 /* "Not supported" implementation */ 561 # define AIF_SET_INIT_AND_DEINIT_FUNCS(FI,FD) /* No-op */ 562 /* Indicate that automatic initialisers/deinitialisers are not supported */ 563 # define AIF_AUTOINIT_FUNCS_ARE_NOT_SUPPORTED 1 564 565 #endif 566 #endif /* !AIF_HEADER_INCLUDED */