Coverage Report

Created: 2026-07-16 07:09

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 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
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 \
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 */