aboutsummaryrefslogtreecommitdiff
path: root/src/include/autoinit_funcs.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/autoinit_funcs.h')
-rw-r--r--src/include/autoinit_funcs.h242
1 files changed, 242 insertions, 0 deletions
diff --git a/src/include/autoinit_funcs.h b/src/include/autoinit_funcs.h
new file mode 100644
index 00000000..2f309e18
--- /dev/null
+++ b/src/include/autoinit_funcs.h
@@ -0,0 +1,242 @@
+/*
+ * AutoinitFuncs: Automatic Initialization and Deinitialization Functions
+ * CopyrightCopyright (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 */