libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

autoinit_funcs.h (12428B)


      1 /*
      2  *  AutoinitFuncs: Automatic Initialization and Deinitialization Functions
      3  *  Copyright(C) 2014-2023 Karlson2k (Evgeny Grin)
      4  *
      5  *  This header is free software; you can redistribute it and / or
      6  *  modify it under the terms of the GNU Lesser General Public
      7  *  License as published by the Free Software Foundation; either
      8  *  version 2.1 of the License, or (at your option) any later version.
      9  *
     10  *  This header is distributed in the hope that it will be useful,
     11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  *  Lesser General Public License for more details.
     14  *
     15  *  You should have received a copy of the GNU Lesser General Public
     16  *  License along with this header; if not, see
     17  *  <http://www.gnu.org/licenses/>.
     18  */
     19 
     20 /*
     21    General usage is simple: include this header, declare or define two
     22    functions with zero parameters (void) and any return type: one for
     23    initialisation and one for deinitialisation, add
     24    _SET_INIT_AND_DEINIT_FUNCS(FuncInitName, FuncDeInitName) to the code
     25    and functions will be automatically called during application startup
     26    and shutdown.
     27    This is useful for libraries as libraries don't have direct access
     28    to main() functions.
     29    Example:
     30    -------------------------------------------------
     31    #include <stdlib.h>
     32    #include "autoinit_funcs.h"
     33 
     34    int someVar;
     35    void* somePtr;
     36 
     37    void libInit(void)
     38    {
     39      someVar = 3;
     40      somePtr = malloc(100);
     41    }
     42 
     43    void libDeinit(void)
     44    {
     45      free(somePtr);
     46    }
     47 
     48    _SET_INIT_AND_DEINIT_FUNCS(libInit,libDeinit);
     49    -------------------------------------------------
     50 
     51    If initialiser or deinitialiser function is not needed, just define
     52    it as empty function.
     53 
     54    This header should work with GCC, clang, MSVC (2010 or later) and
     55    SunPro / Sun Studio / Oracle Solaris Studio / Oracle Developer Studio
     56    compiler.
     57    Supported C and C++ languages; application, static and dynamic (DLL)
     58    libraries; non-optimized (Debug) and optimised (Release) compilation
     59    and linking.
     60 
     61    For more information see header code and comments in code.
     62  */
     63 #ifndef AUTOINIT_FUNCS_INCLUDED
     64 #define AUTOINIT_FUNCS_INCLUDED 1
     65 
     66 /**
     67 * Current version of the header in packed BCD form.
     68 * 0x01093001 = 1.9.30-1.
     69 */
     70 #define AUTOINIT_FUNCS_VERSION 0x01001000
     71 
     72 #if defined(__GNUC__) || defined(__clang__)
     73 /* if possible - check for supported attribute */
     74 #ifdef __has_attribute
     75 #if ! __has_attribute (constructor) || ! __has_attribute (destructor)
     76 #define _GNUC_ATTR_CONSTR_NOT_SUPPORTED 1
     77 #endif /* !__has_attribute(constructor) || !__has_attribute(destructor) */
     78 #endif /* __has_attribute */
     79 #endif /* __GNUC__ */
     80 
     81 /* "__has_attribute__ ((constructor))" is supported by GCC, clang and
     82    Sun/Oracle compiler starting from version 12.1. */
     83 #if ((defined(__GNUC__) || defined(__clang__)) && \
     84   ! defined(_GNUC_ATTR_CONSTR_NOT_SUPPORTED)) || \
     85   (defined(__SUNPRO_C) && __SUNPRO_C + 0 >= 0x5100)
     86 
     87 #define GNUC_SET_INIT_AND_DEINIT(FI,FD) \
     88   void __attribute__ ((constructor)) _GNUC_init_helper_ ## FI (void);  \
     89   void __attribute__ ((destructor)) _GNUC_deinit_helper_ ## FD (void); \
     90   void __attribute__ ((constructor)) _GNUC_init_helper_ ## FI (void)   \
     91   { (void) (FI) (); } \
     92   void __attribute__ ((destructor)) _GNUC_deinit_helper_ ## FD (void)  \
     93   { (void) (FD) (); } \
     94   struct _GNUC_dummy_str_ ## FI {int i;}
     95 
     96 #define _SET_INIT_AND_DEINIT_FUNCS(FI,FD) GNUC_SET_INIT_AND_DEINIT (FI,FD)
     97 #define _AUTOINIT_FUNCS_ARE_SUPPORTED 1
     98 
     99 #elif defined(_MSC_FULL_VER) && _MSC_VER + 0 >= 1600
    100 
    101 /* Make sure that your project/sources define:
    102    _LIB if building a static library (_LIB is ignored if _CONSOLE is defined);
    103    _USRDLL if building DLL-library;
    104    not defined both _LIB and _USRDLL if building an application */
    105 
    106 /* Define AUTOINIT_FUNCS_DECLARE_STATIC_REG if you need macro declaration
    107    for registering static initialisation functions even if you building DLL */
    108 /* Define AUTOINIT_FUNCS_FORCE_STATIC_REG if you want to set main macro
    109    _SET_INIT_AND_DEINIT_FUNCS to static version even if building a DLL */
    110 
    111 /* Stringify macros */
    112 #define _INSTRMACRO(a) #a
    113 #define _STRMACRO(a) _INSTRMACRO (a)
    114 
    115 #if ! defined(_USRDLL) || defined(AUTOINIT_FUNCS_DECLARE_STATIC_REG) \
    116   || defined(AUTOINIT_FUNCS_FORCE_STATIC_REG)
    117 
    118 /* Use "C" linkage for variable to simplify variable decoration */
    119 #ifdef __cplusplus
    120 #define W32_INITVARDECL extern "C"
    121 #else
    122 #define W32_INITVARDECL extern
    123 #endif
    124 
    125 /* How variable is decorated by compiler */
    126 #if (defined(_WIN32) || defined(_WIN64)) \
    127   && ! defined(_M_IX86) && ! defined(_X86_)
    128 #if ! defined(_M_X64) && ! defined(_M_AMD64) && ! defined(_x86_64_) \
    129   && ! defined(_M_ARM) && ! defined(_M_ARM64)
    130 #pragma message(__FILE__ "(" _STRMACRO(__LINE__) ") : warning AIFW001 : " \
    131   "Untested architecture, linker may fail with unresolved symbol")
    132 #endif /* ! _M_X64 && ! _M_AMD64 && ! _x86_64_ && ! _M_ARM && ! _M_ARM64 */
    133 #define W32_VARDECORPREFIX
    134 #define W32_DECORVARNAME(v) v
    135 #define W32_VARDECORPREFIXSTR ""
    136 #elif defined(_WIN32) && (defined(_M_IX86) || defined(_X86_))
    137 #define W32_VARDECORPREFIX _
    138 #define W32_DECORVARNAME(v) _ ## v
    139 #define W32_VARDECORPREFIXSTR "_"
    140 #else
    141 #error Do not know how to decorate symbols for this architecture
    142 #endif
    143 
    144 /* Internal variable prefix (can be any) */
    145 #define W32_INITHELPERVARNAME(f) _initHelperDummy_ ## f
    146 #define W32_INITHELPERVARNAMEDECORSTR(f) \
    147   W32_VARDECORPREFIXSTR _STRMACRO (W32_INITHELPERVARNAME (f))
    148 
    149 /* Declare section (segment), put variable pointing to init function to chosen segment,
    150    force linker to always include variable to avoid omitting by optimiser */
    151 /* Initialisation function must be declared as
    152    void __cdecl FuncName(void) */
    153 /* "extern" with initialisation value means that variable is declared AND defined. */
    154 #define W32_VFPTR_IN_SEG(S,F) \
    155   __pragma (section (S,long,read)) \
    156   __pragma (comment (linker, "/INCLUDE:" W32_INITHELPERVARNAMEDECORSTR (F))) \
    157   W32_INITVARDECL __declspec(allocate (S))void \
    158     (__cdecl * W32_INITHELPERVARNAME (F))(void) = &F
    159 
    160 /* Sections (segments) for pointers to initialisers/deinitialisers */
    161 
    162 /* Semi-officially suggested section for early initialisers (called before
    163    C++ objects initialisers), "void" return type */
    164 #define W32_SEG_INIT_EARLY      ".CRT$XCT"
    165 /* Semi-officially suggested section for late initialisers (called after
    166    C++ objects initialisers), "void" return type */
    167 #define W32_SEG_INIT_LATE       ".CRT$XCV"
    168 
    169 /* Unsafe sections (segments) for pointers to initialisers/deinitialisers */
    170 
    171 /* C++ lib initialisers, "void" return type (reserved by the system!) */
    172 #define W32_SEG_INIT_CXX_LIB    ".CRT$XCL"
    173 /* C++ user initialisers, "void" return type (reserved by the system!) */
    174 #define W32_SEG_INIT_CXX_USER   ".CRT$XCU"
    175 
    176 
    177 /* Declare section (segment), put variable pointing to init function to chosen segment,
    178    force linker to always include variable to avoid omitting by optimiser */
    179 /* Initialisation function must be declared as
    180    int __cdecl FuncName(void) */
    181 /* Startup process is aborted if initialiser returns non-zero */
    182 /* "extern" with initialisation value means that variable is declared AND defined. */
    183 #define W32_IFPTR_IN_SEG(S,F) \
    184   __pragma (section (S,long,read)) \
    185   __pragma (comment (linker, "/INCLUDE:" W32_INITHELPERVARNAMEDECORSTR (F))) \
    186   W32_INITVARDECL __declspec(allocate (S))int \
    187     (__cdecl * W32_INITHELPERVARNAME (F))(void) = &F
    188 
    189 /* Unsafe sections (segments) for pointers to initialisers with
    190    "int" return type */
    191 
    192 /* C lib initialisers, "int" return type (reserved by the system!).
    193    These initialisers are called before others. */
    194 #define W32_SEG_INIT_C_LIB      ".CRT$XIL"
    195 /* C user initialisers, "int" return type (reserved by the system!).
    196    These initialisers are called before others. */
    197 #define W32_SEG_INIT_C_USER     ".CRT$XIU"
    198 
    199 
    200 /* Declare macro for different initialisers sections */
    201 /* Macro can be used several times to register several initialisers */
    202 /* Once function is registered as initialiser, it will be called automatically
    203    during application startup */
    204 #define W32_REG_INIT_EARLY(F) W32_VFPTR_IN_SEG (W32_SEG_INIT_EARLY,F)
    205 #define W32_REG_INIT_LATE(F)  W32_VFPTR_IN_SEG (W32_SEG_INIT_LATE,F)
    206 
    207 
    208 /* Not recommended / unsafe */
    209 /* "lib" initialisers are called before "user" initialisers */
    210 /* "C" initialisers are called before "C++" initialisers */
    211 #define W32_REG_INIT_C_USER(F)   W32_FPTR_IN_SEG (W32_SEG_INIT_C_USER,F)
    212 #define W32_REG_INIT_C_LIB(F)    W32_FPTR_IN_SEG (W32_SEG_INIT_C_LIB,F)
    213 #define W32_REG_INIT_CXX_USER(F) W32_FPTR_IN_SEG (W32_SEG_INIT_CXX_USER,F)
    214 #define W32_REG_INIT_CXX_LIB(F)  W32_FPTR_IN_SEG (W32_SEG_INIT_CXX_LIB,F)
    215 
    216 /* Choose main register macro based on language and program type */
    217 /* Assuming that _LIB or _USRDLL is defined for static or DLL-library */
    218 /* Macro can be used several times to register several initialisers */
    219 /* Once function is registered as initialiser, it will be called automatically
    220    during application startup */
    221 /* Define AUTOINIT_FUNCS_FORCE_EARLY_INIT to force register as early
    222    initialiser */
    223 /* Define AUTOINIT_FUNCS_FORCE_LATE_INIT to force register as late
    224    initialiser */
    225 /* By default C++ static or DLL-library code and any C code and will be
    226    registered as early initialiser, while C++ non-library code will be
    227    registered as late initialiser */
    228 #if (! defined(__cplusplus) || \
    229   ((defined(_LIB) && ! defined(_CONSOLE)) || defined(_USRDLL)) || \
    230   defined(AUTOINIT_FUNCS_FORCE_EARLY_INIT)) && \
    231   ! defined(AUTOINIT_FUNCS_FORCE_LATE_INIT)
    232 #define W32_REGISTER_INIT(F) W32_REG_INIT_EARLY(F)
    233 #else
    234 #define W32_REGISTER_INIT(F) W32_REG_INIT_LATE(F)
    235 #endif
    236 
    237 #endif /* ! _USRDLL || ! AUTOINIT_FUNCS_DECLARE_STATIC_REG
    238           || AUTOINIT_FUNCS_FORCE_STATIC_REG */
    239 
    240 
    241 #if ! defined(_USRDLL) || defined(AUTOINIT_FUNCS_FORCE_STATIC_REG)
    242 
    243 #include <stdlib.h> /* required for atexit() */
    244 
    245 #define W32_SET_INIT_AND_DEINIT(FI,FD) \
    246   void __cdecl _W32_init_helper_ ## FI (void);    \
    247   void __cdecl _W32_deinit_helper_ ## FD (void); \
    248   void __cdecl _W32_init_helper_ ## FI (void)     \
    249   { (void) (FI) (); atexit (_W32_deinit_helper_ ## FD); } \
    250   void __cdecl _W32_deinit_helper_ ## FD (void)  \
    251   { (void) (FD) (); } \
    252   W32_REGISTER_INIT (_W32_init_helper_ ## FI)
    253 #else  /* _USRDLL */
    254 
    255 #ifndef WIN32_LEAN_AND_MEAN
    256 #define WIN32_LEAN_AND_MEAN 1
    257 #endif /* WIN32_LEAN_AND_MEAN */
    258 
    259 #include <Windows.h> /* Required for DllMain */
    260 
    261 /* If DllMain is already present in code, define AUTOINIT_FUNCS_CALL_USR_DLLMAIN
    262    and rename DllMain to usr_DllMain */
    263 #ifndef AUTOINIT_FUNCS_CALL_USR_DLLMAIN
    264 #define W32_SET_INIT_AND_DEINIT(FI,FD) \
    265   BOOL WINAPI DllMain (HINSTANCE hinst,DWORD reason,LPVOID unused); \
    266   BOOL WINAPI DllMain (HINSTANCE hinst,DWORD reason,LPVOID unused)  \
    267   { (void) hinst; (void) unused; \
    268     if (DLL_PROCESS_ATTACH==reason) {(void) (FI) ();} \
    269     else if (DLL_PROCESS_DETACH==reason) {(void) (FD) ();} \
    270     return TRUE; \
    271   } struct _W32_dummy_strc_ ## FI {int i;}
    272 #else  /* AUTOINIT_FUNCS_CALL_USR_DLLMAIN */
    273 #define W32_SET_INIT_AND_DEINIT(FI,FD) \
    274   BOOL WINAPI usr_DllMain (HINSTANCE hinst,DWORD reason,LPVOID unused); \
    275   BOOL WINAPI DllMain (HINSTANCE hinst,DWORD reason,LPVOID unused); \
    276   BOOL WINAPI DllMain (HINSTANCE hinst,DWORD reason,LPVOID unused)  \
    277   { if (DLL_PROCESS_ATTACH==reason) {(void) (FI) ();} \
    278     else if (DLL_PROCESS_DETACH==reason) {(void) (FD) ();} \
    279     return usr_DllMain (hinst,reason,unused); \
    280   } struct _W32_dummy_strc_ ## FI {int i;}
    281 #endif /* AUTOINIT_FUNCS_CALL_USR_DLLMAIN */
    282 #endif /* _USRDLL */
    283 
    284 #define _SET_INIT_AND_DEINIT_FUNCS(FI,FD) W32_SET_INIT_AND_DEINIT (FI,FD)
    285 /* Indicate that automatic initialisers/deinitialisers are supported */
    286 #define _AUTOINIT_FUNCS_ARE_SUPPORTED 1
    287 
    288 #else  /* !__GNUC__ && !_MSC_FULL_VER */
    289 
    290 /* Define EMIT_ERROR_IF_AUTOINIT_FUNCS_ARE_NOT_SUPPORTED before inclusion of header to
    291    abort compilation if automatic initialisers/deinitialisers are not supported */
    292 #ifdef EMIT_ERROR_IF_AUTOINIT_FUNCS_ARE_NOT_SUPPORTED
    293 #error \
    294   Compiler/platform does not support automatic calls of user-defined initializer and deinitializer
    295 #endif /* EMIT_ERROR_IF_AUTOINIT_FUNCS_ARE_NOT_SUPPORTED */
    296 
    297 /* Do nothing */
    298 #define _SET_INIT_AND_DEINIT_FUNCS(FI,FD)
    299 /* Indicate that automatic initialisers/deinitialisers are not supported */
    300 #define _AUTOINIT_FUNCS_ARE_NOT_SUPPORTED 1
    301 
    302 #endif /* !__GNUC__ && !_MSC_FULL_VER */
    303 #endif /* !AUTOINIT_FUNCS_INCLUDED */