libmicrohttpd2

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

autoinit_funcs.h (25364B)


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