libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

autoinit_funcs.h (25654B)


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