libmicrohttpd

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

commit 9303922d4787ef1d166264d452c0608323e7bead
parent 684be54c9fd602b52870ea3c477e435aae4e5b49
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
Date:   Mon, 22 Dec 2014 19:43:04 +0000

Add and use header for multiplatform support of Init/Deinit functions

Diffstat:
Asrc/include/autoinit_funcs.h | 242+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/microhttpd/daemon.c | 15+++++----------
2 files changed, 247 insertions(+), 10 deletions(-)

diff --git a/src/include/autoinit_funcs.h b/src/include/autoinit_funcs.h @@ -0,0 +1,242 @@ +/* + * AutoinitFuncs: Automatic Initialization and Deinitialization Functions + * Copyright(C) 2014 Karlson2k (Evgeny Grin) + * + * This header is free software; you can redistribute it and / or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This header is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this header; if not, see + * <http://www.gnu.org/licenses/>. + */ + +/* + General usage is simple: include this header, declare or define two + functions with zero parameters (void) and any return type: one for + initialization and one for deinitialization, add + _SET_INIT_AND_DEINIT_FUNCS(FuncInitName, FuncDeInitName) to the code + and functions will be automatically called during application startup + and shutdown. + This is useful for libraries as libraries doesn't have direct access + to main() functions. + Example: + ------------------------------------------------- + #include <stdlib.h> + #include "autoinit_funcs.h" + + int someVar; + void* somePtr; + + void libInit(void) + { + someVar = 3; + somePtr = malloc(100); + } + + void libDeinit(void) + { + free(somePtr); + } + + _SET_INIT_AND_DEINIT_FUNCS(libInit,libDeinit); + ------------------------------------------------- + + If initializer or deinitializer functions is not needed, just define + it as empty function. + + This header should work with GCC, clang, MSVC (2010 or later). + Supported C and C++ languages; application, static and dynamic (DLL) + libraries; non-optimized (Debug) and optimized (Release) compilation + and linking. + + For more information see header code and comments in code. + */ +#ifndef AUTOINIT_FUNCS_INCLUDED +#define AUTOINIT_FUNCS_INCLUDED 1 + +/** +* Current version of the header. +* 0x01093001 = 1.9.30-1. +*/ +#define AUTOINIT_FUNCS_VERSION 0x01000001 + +#if defined(__GNUC__) +#/* if possible - check for supported attribute */ +#ifdef __has_attribute +#if !__has_attribute(constructor) || !__has_attribute(destructor) +#define _GNUC_ATTR_CONSTR_NOT_SUPPORTED 1 +#endif /* !__has_attribute(constructor) || !__has_attribute(destructor) */ +#endif /* __has_attribute */ +#endif /* __GNUC__ */ + +#if defined(__GNUC__) && !defined(_GNUC_ATTR_CONSTR_NOT_SUPPORTED) + +#define GNUC_SET_INIT_AND_DEINIT(FI,FD) \ + void __attribute__ ((constructor)) _GNUC_init_helper_##FI(void) \ + { (void)(FI)(); } \ + void __attribute__ ((destructor)) _GNUC_deinit_helper_##FD(void) \ + { (void)(FD)(); } \ + struct _GNUC_dummy_str_##FI{int i;} + +#define _SET_INIT_AND_DEINIT_FUNCS(FI,FD) GNUC_SET_INIT_AND_DEINIT(FI,FD) +#define _AUTOINIT_FUNCS_ARE_SUPPORTED 1 + +#elif defined (_MSC_FULL_VER) && _MSC_VER+0 >= 1600 + +/* Make sure that your project/sources define: + _LIB if building a static library (_LIB is ignored if _CONSOLE is defined); + _USRDLL if building DLL-library; + not defined both _LIB and _USRDLL if building an application */ + +/* Define AUTOINIT_FUNCS_DECLARE_STATIC_REG if you need macro declaration + for registering static initialization functions even if you building DLL */ +/* Define AUTOINIT_FUNCS_FORCE_STATIC_REG if you want to set main macro + _SET_INIT_AND_DEINIT_FUNCS to static version even if building a DLL*/ + +/* Stringify macros */ +#define _INSTRMACRO(a) #a +#define _STRMACRO(a) _INSTRMACRO(a) + +#if !defined(_USRDLL) || defined(AUTOINIT_FUNCS_DECLARE_STATIC_REG) + +/* required for atexit() */ +#include <stdlib.h> + +/* Use "C" linkage for variable to simplify variable decoration */ +#ifdef __cplusplus +#define W32_INITVARDECL extern "C" +#else +#define W32_INITVARDECL extern +#endif + +/* How variable is decorated by compiler */ +#if defined(_M_X64) || defined(_M_AMD64) +#define W32_VARDECORPREFIX +#define W32_DECORVARNAME(v) v +#define W32_VARDECORPEFIXSTR "" +#elif defined(_M_IX86) || defined(_X86_) +#define W32_VARDECORPREFIX _ +#define W32_DECORVARNAME(v) _##v +#define W32_VARDECORPEFIXSTR "_" +#else +#error Do not know how to decorate symbols for this architecture +#endif + +/* Internal variable prefix (can be any) */ +#define W32_INITHELPERVARNAME(f) _initHelperDummy_##f +#define W32_INITHELPERVARNAMEDECORSTR(f) W32_VARDECORPEFIXSTR _STRMACRO(W32_INITHELPERVARNAME(f)) + +/* Declare section (segment), put variable pointing to init function to chosen segment, + force linker to include variable to avoid omitting by optimizer */ +/* Initialization function must be declared as + int __cdecl FuncName(void) */ +/* Return value is ignored for C++ initializers */ +/* For C initializers: startup process is aborted if initializer return non-zero */ +#define W32_FPTR_IN_SEG(S,F) \ + __pragma(section(S,long,read)) \ + __pragma(comment(linker, "/INCLUDE:" W32_INITHELPERVARNAMEDECORSTR(F))) \ + W32_INITVARDECL __declspec(allocate(S)) int(__cdecl *W32_INITHELPERVARNAME(F))(void) = &F + +/* Section (segment) names for pointers to initializers */ +#define W32_SEG_INIT_C_USER ".CRT$XCU" +#define W32_SEG_INIT_C_LIB ".CRT$XCL" +#define W32_SEG_INIT_CXX_USER ".CRT$XIU" +#define W32_SEG_INIT_CXX_LIB ".CRT$XIL" + +/* Declare macro for different initializers sections */ +/* Macro can be used several times to register several initializers */ +/* Once function is registered as initializer, it will be called automatically + during application startup */ +/* "lib" initializers are called before "user" initializers */ +/* "C" initializers are called before "C++" initializers */ +#define W32_REG_INIT_C_USER(F) W32_FPTR_IN_SEG(W32_SEG_INIT_C_USER,F) +#define W32_REG_INIT_C_LIB(F) W32_FPTR_IN_SEG(W32_SEG_INIT_C_LIB,F) +#define W32_REG_INIT_CXX_USER(F) W32_FPTR_IN_SEG(W32_SEG_INIT_CXX_USER,F) +#define W32_REG_INIT_CXX_LIB(F) W32_FPTR_IN_SEG(W32_SEG_INIT_CXX_LIB,F) + +/* Choose main register macro based on language and program type */ +/* Assuming that _LIB or _USRDLL is defined for static or DLL-library */ +/* Macro can be used several times to register several initializers */ +/* Once function is registered as initializer, it will be called automatically + during application startup */ +/* Define AUTOINIT_FUNCS_FORCE_USER_LVL_INIT to register initializers + at user level even if building library */ +#ifdef __cplusplus +#if ((defined(_LIB) && !defined(_CONSOLE)) || defined(_USRDLL)) && !defined(AUTOINIT_FUNCS_FORCE_USER_LVL_INIT) +#define W32_REGISTER_INIT(F) W32_REG_INIT_CXX_LIB(F) +#else /* ! _LIB && ! _DLL */ +#define W32_REGISTER_INIT(F) W32_REG_INIT_CXX_USER(F) +#endif /* ! _LIB && ! _DLL */ +#else /* !__cplusplus*/ +#if ((defined(_LIB) && !defined(_CONSOLE)) || defined(_USRDLL)) && !defined(AUTOINIT_FUNCS_FORCE_USER_LVL_INIT) +#define W32_REGISTER_INIT(F) W32_REG_INIT_C_LIB(F) +#else /* ! _LIB && ! _DLL */ +#define W32_REGISTER_INIT(F) W32_REG_INIT_C_USER(F) +#endif /* ! _LIB && ! _DLL */ +#endif /* !__cplusplus*/ + +#else /* _USRDLL */ + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN 1 +#endif /* WIN32_LEAN_AND_MEAN */ +/* Required for DllMain */ +#include <Windows.h> +#endif /* _USRDLL */ + + +#if !defined(_USRDLL) || defined(AUTOINIT_FUNCS_FORCE_STATIC_REG) +#define W32_SET_INIT_AND_DEINIT(FI,FD) \ + void __cdecl _W32_deinit_helper_##FD(void) \ + { (void)(FD)(); } \ + int __cdecl _W32_init_helper_##FI(void) \ + { (void)(FI)(); atexit(_W32_deinit_helper_##FD); return 0; } \ + W32_REGISTER_INIT(_W32_init_helper_##FI) +#else /* _USRDLL */ + +/* If DllMain is already present in code, define AUTOINIT_FUNCS_CALL_USR_DLLMAIN + and rename DllMain to usr_DllMain */ +#ifndef AUTOINIT_FUNCS_CALL_USR_DLLMAIN +#define W32_SET_INIT_AND_DEINIT(FI,FD) \ + BOOL WINAPI DllMain(HINSTANCE hinst,DWORD reason,LPVOID unused) \ + { if(DLL_PROCESS_ATTACH==reason) {(void)(FI)();} \ + else if(DLL_PROCESS_DETACH==reason) {(void)(FD)();} \ + return TRUE; \ + } struct _W32_dummy_strc_##FI{int i;} +#else /* AUTOINIT_FUNCS_CALL_USR_DLLMAIN */ +#define W32_SET_INIT_AND_DEINIT(FI,FD) \ + BOOL WINAPI usr_DllMain(HINSTANCE hinst,DWORD reason,LPVOID unused); \ + BOOL WINAPI DllMain(HINSTANCE hinst,DWORD reason,LPVOID unused) \ + { if(DLL_PROCESS_ATTACH==reason) {(void)(FI)();} \ + else if(DLL_PROCESS_DETACH==reason) {(void)(FD)();} \ + return usr_DllMain(hinst,reason,unused); \ + } struct _W32_dummy_strc_##FI{int i;} +#endif /* AUTOINIT_FUNCS_CALL_USR_DLLMAIN */ +#endif /* _USRDLL */ + +#define _SET_INIT_AND_DEINIT_FUNCS(FI,FD) W32_SET_INIT_AND_DEINIT(FI,FD) +/* Indicate that automatic initializers/deinitializers are supported */ +#define _AUTOINIT_FUNCS_ARE_SUPPORTED 1 + +#else /* !__GNUC__ && !_MSC_FULL_VER */ + +/* Define EMIT_ERROR_IF_AUTOINIT_FUNCS_ARE_NOT_SUPPORTED before inclusion of header to + abort compilation if automatic initializers/deinitializers are not supported */ +#ifdef EMIT_ERROR_IF_AUTOINIT_FUNCS_ARE_NOT_SUPPORTED +#error Compiler/platform don not support automatic calls of user-defined initializer and deinitializer +#endif /* EMIT_ERROR_IF_AUTOINIT_FUNCS_ARE_NOT_SUPPORTED */ + +/* Do nothing */ +#define _SET_INIT_AND_DEINIT_FUNCS(FI,FD) +/* Indicate that automatic initializers/deinitializers are not supported */ +#define _AUTOINIT_FUNCS_ARE_NOT_SUPPORTED 1 + +#endif /* !__GNUC__ && !_MSC_FULL_VER */ +#endif /* !AUTOINIT_FUNCS_INCLUDED */ diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c @@ -37,6 +37,7 @@ #include "connection.h" #include "memorypool.h" #include <limits.h> +#include "autoinit_funcs.h" #if HAVE_SEARCH_H #include <search.h> @@ -4538,14 +4539,6 @@ MHD_is_feature_supported(enum MHD_FEATURE feature) } -#ifdef __GNUC__ -#define FUNC_CONSTRUCTOR(f) static void __attribute__ ((constructor)) f -#define FUNC_DESTRUCTOR(f) static void __attribute__ ((destructor)) f -#else // !__GNUC__ -#define FUNC_CONSTRUCTOR(f) _MHD_EXTERN void f -#define FUNC_DESTRUCTOR(f) _MHD_EXTERN void f -#endif // __GNUC__ - #if HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600 #if defined(MHD_USE_POSIX_THREADS) GCRY_THREAD_OPTION_PTHREAD_IMPL; @@ -4587,7 +4580,7 @@ static struct gcry_thread_cbs gcry_threads_w32 = { /** * Initialize do setup work. */ -FUNC_CONSTRUCTOR (MHD_init) () +void MHD_init(void) { mhd_panic = &mhd_panic_std; mhd_panic_cls = NULL; @@ -4619,7 +4612,7 @@ FUNC_CONSTRUCTOR (MHD_init) () } -FUNC_DESTRUCTOR (MHD_fini) () +void MHD_fini(void) { #if HTTPS_SUPPORT gnutls_global_deinit (); @@ -4630,5 +4623,7 @@ FUNC_DESTRUCTOR (MHD_fini) () #endif } +_SET_INIT_AND_DEINIT_FUNCS(MHD_init, MHD_fini); + /* end of daemon.c */