diff options
author | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2014-12-22 19:43:04 +0000 |
---|---|---|
committer | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2014-12-22 19:43:04 +0000 |
commit | 9303922d4787ef1d166264d452c0608323e7bead (patch) | |
tree | 850dcf658c1ac3e8986667d09cd21d77cb74054b | |
parent | 684be54c9fd602b52870ea3c477e435aae4e5b49 (diff) | |
download | libmicrohttpd-9303922d4787ef1d166264d452c0608323e7bead.tar.gz libmicrohttpd-9303922d4787ef1d166264d452c0608323e7bead.zip |
Add and use header for multiplatform support of Init/Deinit functions
-rw-r--r-- | src/include/autoinit_funcs.h | 242 | ||||
-rw-r--r-- | src/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 new file mode 100644 index 00000000..dfc54616 --- /dev/null +++ b/src/include/autoinit_funcs.h | |||
@@ -0,0 +1,242 @@ | |||
1 | /* | ||
2 | * AutoinitFuncs: Automatic Initialization and Deinitialization Functions | ||
3 | * Copyright(C) 2014 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 | initialization and one for deinitialization, 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 doesn'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 initializer or deinitializer functions is not needed, just define | ||
52 | it as empty function. | ||
53 | |||
54 | This header should work with GCC, clang, MSVC (2010 or later). | ||
55 | Supported C and C++ languages; application, static and dynamic (DLL) | ||
56 | libraries; non-optimized (Debug) and optimized (Release) compilation | ||
57 | and linking. | ||
58 | |||
59 | For more information see header code and comments in code. | ||
60 | */ | ||
61 | #ifndef AUTOINIT_FUNCS_INCLUDED | ||
62 | #define AUTOINIT_FUNCS_INCLUDED 1 | ||
63 | |||
64 | /** | ||
65 | * Current version of the header. | ||
66 | * 0x01093001 = 1.9.30-1. | ||
67 | */ | ||
68 | #define AUTOINIT_FUNCS_VERSION 0x01000001 | ||
69 | |||
70 | #if defined(__GNUC__) | ||
71 | #/* if possible - check for supported attribute */ | ||
72 | #ifdef __has_attribute | ||
73 | #if !__has_attribute(constructor) || !__has_attribute(destructor) | ||
74 | #define _GNUC_ATTR_CONSTR_NOT_SUPPORTED 1 | ||
75 | #endif /* !__has_attribute(constructor) || !__has_attribute(destructor) */ | ||
76 | #endif /* __has_attribute */ | ||
77 | #endif /* __GNUC__ */ | ||
78 | |||
79 | #if defined(__GNUC__) && !defined(_GNUC_ATTR_CONSTR_NOT_SUPPORTED) | ||
80 | |||
81 | #define GNUC_SET_INIT_AND_DEINIT(FI,FD) \ | ||
82 | void __attribute__ ((constructor)) _GNUC_init_helper_##FI(void) \ | ||
83 | { (void)(FI)(); } \ | ||
84 | void __attribute__ ((destructor)) _GNUC_deinit_helper_##FD(void) \ | ||
85 | { (void)(FD)(); } \ | ||
86 | struct _GNUC_dummy_str_##FI{int i;} | ||
87 | |||
88 | #define _SET_INIT_AND_DEINIT_FUNCS(FI,FD) GNUC_SET_INIT_AND_DEINIT(FI,FD) | ||
89 | #define _AUTOINIT_FUNCS_ARE_SUPPORTED 1 | ||
90 | |||
91 | #elif defined (_MSC_FULL_VER) && _MSC_VER+0 >= 1600 | ||
92 | |||
93 | /* Make sure that your project/sources define: | ||
94 | _LIB if building a static library (_LIB is ignored if _CONSOLE is defined); | ||
95 | _USRDLL if building DLL-library; | ||
96 | not defined both _LIB and _USRDLL if building an application */ | ||
97 | |||
98 | /* Define AUTOINIT_FUNCS_DECLARE_STATIC_REG if you need macro declaration | ||
99 | for registering static initialization functions even if you building DLL */ | ||
100 | /* Define AUTOINIT_FUNCS_FORCE_STATIC_REG if you want to set main macro | ||
101 | _SET_INIT_AND_DEINIT_FUNCS to static version even if building a DLL*/ | ||
102 | |||
103 | /* Stringify macros */ | ||
104 | #define _INSTRMACRO(a) #a | ||
105 | #define _STRMACRO(a) _INSTRMACRO(a) | ||
106 | |||
107 | #if !defined(_USRDLL) || defined(AUTOINIT_FUNCS_DECLARE_STATIC_REG) | ||
108 | |||
109 | /* required for atexit() */ | ||
110 | #include <stdlib.h> | ||
111 | |||
112 | /* Use "C" linkage for variable to simplify variable decoration */ | ||
113 | #ifdef __cplusplus | ||
114 | #define W32_INITVARDECL extern "C" | ||
115 | #else | ||
116 | #define W32_INITVARDECL extern | ||
117 | #endif | ||
118 | |||
119 | /* How variable is decorated by compiler */ | ||
120 | #if defined(_M_X64) || defined(_M_AMD64) | ||
121 | #define W32_VARDECORPREFIX | ||
122 | #define W32_DECORVARNAME(v) v | ||
123 | #define W32_VARDECORPEFIXSTR "" | ||
124 | #elif defined(_M_IX86) || defined(_X86_) | ||
125 | #define W32_VARDECORPREFIX _ | ||
126 | #define W32_DECORVARNAME(v) _##v | ||
127 | #define W32_VARDECORPEFIXSTR "_" | ||
128 | #else | ||
129 | #error Do not know how to decorate symbols for this architecture | ||
130 | #endif | ||
131 | |||
132 | /* Internal variable prefix (can be any) */ | ||
133 | #define W32_INITHELPERVARNAME(f) _initHelperDummy_##f | ||
134 | #define W32_INITHELPERVARNAMEDECORSTR(f) W32_VARDECORPEFIXSTR _STRMACRO(W32_INITHELPERVARNAME(f)) | ||
135 | |||
136 | /* Declare section (segment), put variable pointing to init function to chosen segment, | ||
137 | force linker to include variable to avoid omitting by optimizer */ | ||
138 | /* Initialization function must be declared as | ||
139 | int __cdecl FuncName(void) */ | ||
140 | /* Return value is ignored for C++ initializers */ | ||
141 | /* For C initializers: startup process is aborted if initializer return non-zero */ | ||
142 | #define W32_FPTR_IN_SEG(S,F) \ | ||
143 | __pragma(section(S,long,read)) \ | ||
144 | __pragma(comment(linker, "/INCLUDE:" W32_INITHELPERVARNAMEDECORSTR(F))) \ | ||
145 | W32_INITVARDECL __declspec(allocate(S)) int(__cdecl *W32_INITHELPERVARNAME(F))(void) = &F | ||
146 | |||
147 | /* Section (segment) names for pointers to initializers */ | ||
148 | #define W32_SEG_INIT_C_USER ".CRT$XCU" | ||
149 | #define W32_SEG_INIT_C_LIB ".CRT$XCL" | ||
150 | #define W32_SEG_INIT_CXX_USER ".CRT$XIU" | ||
151 | #define W32_SEG_INIT_CXX_LIB ".CRT$XIL" | ||
152 | |||
153 | /* Declare macro for different initializers sections */ | ||
154 | /* Macro can be used several times to register several initializers */ | ||
155 | /* Once function is registered as initializer, it will be called automatically | ||
156 | during application startup */ | ||
157 | /* "lib" initializers are called before "user" initializers */ | ||
158 | /* "C" initializers are called before "C++" initializers */ | ||
159 | #define W32_REG_INIT_C_USER(F) W32_FPTR_IN_SEG(W32_SEG_INIT_C_USER,F) | ||
160 | #define W32_REG_INIT_C_LIB(F) W32_FPTR_IN_SEG(W32_SEG_INIT_C_LIB,F) | ||
161 | #define W32_REG_INIT_CXX_USER(F) W32_FPTR_IN_SEG(W32_SEG_INIT_CXX_USER,F) | ||
162 | #define W32_REG_INIT_CXX_LIB(F) W32_FPTR_IN_SEG(W32_SEG_INIT_CXX_LIB,F) | ||
163 | |||
164 | /* Choose main register macro based on language and program type */ | ||
165 | /* Assuming that _LIB or _USRDLL is defined for static or DLL-library */ | ||
166 | /* Macro can be used several times to register several initializers */ | ||
167 | /* Once function is registered as initializer, it will be called automatically | ||
168 | during application startup */ | ||
169 | /* Define AUTOINIT_FUNCS_FORCE_USER_LVL_INIT to register initializers | ||
170 | at user level even if building library */ | ||
171 | #ifdef __cplusplus | ||
172 | #if ((defined(_LIB) && !defined(_CONSOLE)) || defined(_USRDLL)) && !defined(AUTOINIT_FUNCS_FORCE_USER_LVL_INIT) | ||
173 | #define W32_REGISTER_INIT(F) W32_REG_INIT_CXX_LIB(F) | ||
174 | #else /* ! _LIB && ! _DLL */ | ||
175 | #define W32_REGISTER_INIT(F) W32_REG_INIT_CXX_USER(F) | ||
176 | #endif /* ! _LIB && ! _DLL */ | ||
177 | #else /* !__cplusplus*/ | ||
178 | #if ((defined(_LIB) && !defined(_CONSOLE)) || defined(_USRDLL)) && !defined(AUTOINIT_FUNCS_FORCE_USER_LVL_INIT) | ||
179 | #define W32_REGISTER_INIT(F) W32_REG_INIT_C_LIB(F) | ||
180 | #else /* ! _LIB && ! _DLL */ | ||
181 | #define W32_REGISTER_INIT(F) W32_REG_INIT_C_USER(F) | ||
182 | #endif /* ! _LIB && ! _DLL */ | ||
183 | #endif /* !__cplusplus*/ | ||
184 | |||
185 | #else /* _USRDLL */ | ||
186 | |||
187 | #ifndef WIN32_LEAN_AND_MEAN | ||
188 | #define WIN32_LEAN_AND_MEAN 1 | ||
189 | #endif /* WIN32_LEAN_AND_MEAN */ | ||
190 | /* Required for DllMain */ | ||
191 | #include <Windows.h> | ||
192 | #endif /* _USRDLL */ | ||
193 | |||
194 | |||
195 | #if !defined(_USRDLL) || defined(AUTOINIT_FUNCS_FORCE_STATIC_REG) | ||
196 | #define W32_SET_INIT_AND_DEINIT(FI,FD) \ | ||
197 | void __cdecl _W32_deinit_helper_##FD(void) \ | ||
198 | { (void)(FD)(); } \ | ||
199 | int __cdecl _W32_init_helper_##FI(void) \ | ||
200 | { (void)(FI)(); atexit(_W32_deinit_helper_##FD); return 0; } \ | ||
201 | W32_REGISTER_INIT(_W32_init_helper_##FI) | ||
202 | #else /* _USRDLL */ | ||
203 | |||
204 | /* If DllMain is already present in code, define AUTOINIT_FUNCS_CALL_USR_DLLMAIN | ||
205 | and rename DllMain to usr_DllMain */ | ||
206 | #ifndef AUTOINIT_FUNCS_CALL_USR_DLLMAIN | ||
207 | #define W32_SET_INIT_AND_DEINIT(FI,FD) \ | ||
208 | BOOL WINAPI DllMain(HINSTANCE hinst,DWORD reason,LPVOID unused) \ | ||
209 | { if(DLL_PROCESS_ATTACH==reason) {(void)(FI)();} \ | ||
210 | else if(DLL_PROCESS_DETACH==reason) {(void)(FD)();} \ | ||
211 | return TRUE; \ | ||
212 | } struct _W32_dummy_strc_##FI{int i;} | ||
213 | #else /* AUTOINIT_FUNCS_CALL_USR_DLLMAIN */ | ||
214 | #define W32_SET_INIT_AND_DEINIT(FI,FD) \ | ||
215 | BOOL WINAPI usr_DllMain(HINSTANCE hinst,DWORD reason,LPVOID unused); \ | ||
216 | BOOL WINAPI DllMain(HINSTANCE hinst,DWORD reason,LPVOID unused) \ | ||
217 | { if(DLL_PROCESS_ATTACH==reason) {(void)(FI)();} \ | ||
218 | else if(DLL_PROCESS_DETACH==reason) {(void)(FD)();} \ | ||
219 | return usr_DllMain(hinst,reason,unused); \ | ||
220 | } struct _W32_dummy_strc_##FI{int i;} | ||
221 | #endif /* AUTOINIT_FUNCS_CALL_USR_DLLMAIN */ | ||
222 | #endif /* _USRDLL */ | ||
223 | |||
224 | #define _SET_INIT_AND_DEINIT_FUNCS(FI,FD) W32_SET_INIT_AND_DEINIT(FI,FD) | ||
225 | /* Indicate that automatic initializers/deinitializers are supported */ | ||
226 | #define _AUTOINIT_FUNCS_ARE_SUPPORTED 1 | ||
227 | |||
228 | #else /* !__GNUC__ && !_MSC_FULL_VER */ | ||
229 | |||
230 | /* Define EMIT_ERROR_IF_AUTOINIT_FUNCS_ARE_NOT_SUPPORTED before inclusion of header to | ||
231 | abort compilation if automatic initializers/deinitializers are not supported */ | ||
232 | #ifdef EMIT_ERROR_IF_AUTOINIT_FUNCS_ARE_NOT_SUPPORTED | ||
233 | #error Compiler/platform don not support automatic calls of user-defined initializer and deinitializer | ||
234 | #endif /* EMIT_ERROR_IF_AUTOINIT_FUNCS_ARE_NOT_SUPPORTED */ | ||
235 | |||
236 | /* Do nothing */ | ||
237 | #define _SET_INIT_AND_DEINIT_FUNCS(FI,FD) | ||
238 | /* Indicate that automatic initializers/deinitializers are not supported */ | ||
239 | #define _AUTOINIT_FUNCS_ARE_NOT_SUPPORTED 1 | ||
240 | |||
241 | #endif /* !__GNUC__ && !_MSC_FULL_VER */ | ||
242 | #endif /* !AUTOINIT_FUNCS_INCLUDED */ | ||
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c index 66453094..0816a4a9 100644 --- a/src/microhttpd/daemon.c +++ b/src/microhttpd/daemon.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include "connection.h" | 37 | #include "connection.h" |
38 | #include "memorypool.h" | 38 | #include "memorypool.h" |
39 | #include <limits.h> | 39 | #include <limits.h> |
40 | #include "autoinit_funcs.h" | ||
40 | 41 | ||
41 | #if HAVE_SEARCH_H | 42 | #if HAVE_SEARCH_H |
42 | #include <search.h> | 43 | #include <search.h> |
@@ -4538,14 +4539,6 @@ MHD_is_feature_supported(enum MHD_FEATURE feature) | |||
4538 | } | 4539 | } |
4539 | 4540 | ||
4540 | 4541 | ||
4541 | #ifdef __GNUC__ | ||
4542 | #define FUNC_CONSTRUCTOR(f) static void __attribute__ ((constructor)) f | ||
4543 | #define FUNC_DESTRUCTOR(f) static void __attribute__ ((destructor)) f | ||
4544 | #else // !__GNUC__ | ||
4545 | #define FUNC_CONSTRUCTOR(f) _MHD_EXTERN void f | ||
4546 | #define FUNC_DESTRUCTOR(f) _MHD_EXTERN void f | ||
4547 | #endif // __GNUC__ | ||
4548 | |||
4549 | #if HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600 | 4542 | #if HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600 |
4550 | #if defined(MHD_USE_POSIX_THREADS) | 4543 | #if defined(MHD_USE_POSIX_THREADS) |
4551 | GCRY_THREAD_OPTION_PTHREAD_IMPL; | 4544 | GCRY_THREAD_OPTION_PTHREAD_IMPL; |
@@ -4587,7 +4580,7 @@ static struct gcry_thread_cbs gcry_threads_w32 = { | |||
4587 | /** | 4580 | /** |
4588 | * Initialize do setup work. | 4581 | * Initialize do setup work. |
4589 | */ | 4582 | */ |
4590 | FUNC_CONSTRUCTOR (MHD_init) () | 4583 | void MHD_init(void) |
4591 | { | 4584 | { |
4592 | mhd_panic = &mhd_panic_std; | 4585 | mhd_panic = &mhd_panic_std; |
4593 | mhd_panic_cls = NULL; | 4586 | mhd_panic_cls = NULL; |
@@ -4619,7 +4612,7 @@ FUNC_CONSTRUCTOR (MHD_init) () | |||
4619 | } | 4612 | } |
4620 | 4613 | ||
4621 | 4614 | ||
4622 | FUNC_DESTRUCTOR (MHD_fini) () | 4615 | void MHD_fini(void) |
4623 | { | 4616 | { |
4624 | #if HTTPS_SUPPORT | 4617 | #if HTTPS_SUPPORT |
4625 | gnutls_global_deinit (); | 4618 | gnutls_global_deinit (); |
@@ -4630,5 +4623,7 @@ FUNC_DESTRUCTOR (MHD_fini) () | |||
4630 | #endif | 4623 | #endif |
4631 | } | 4624 | } |
4632 | 4625 | ||
4626 | _SET_INIT_AND_DEINIT_FUNCS(MHD_init, MHD_fini); | ||
4627 | |||
4633 | /* end of daemon.c */ | 4628 | /* end of daemon.c */ |
4634 | 4629 | ||