Coverage Report

Created: 2025-10-27 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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 */