/src/mhd2/src/incl_priv/autoinit_funcs.h
Line | Count | Source |
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 | 4 | { (void) (FI) (); } \ |
140 | | void __attribute__ ((destructor)) AIF_GNUC_deinit_helper_ ## FD (void) \ |
141 | 0 | { (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 */ |