/* Interface to external module (*Serv) symbols for database modules.
*
* IRC Services is copyright (c) 1996-2007 Andrew Church.
* E-mail: <achurch@achurch.org>
* Parts written by Andrew Kempe and others.
* This program is free but copyrighted software; see the file COPYING for
* details.
*/
#include "services.h"
#include "modules.h"
#define IN_EXTSYMS_C
#include "extsyms.h"
/*************************************************************************/
#ifdef __INTEL_COMPILER /* icc hides the symbols from the inline asm */
# define static
#endif
static Module *module_nickserv;
static Module *module_chanserv;
static Module *module_memoserv;
static Module *module_operserv;
static Module *module_statserv;
#ifdef __INTEL_COMPILER
# undef static
#endif
static const char *this_module_name = "(unknown-module)";
/*************************************************************************/
static void fatal_no_symbol(const char *symbol)
{
fatal("%s: undefined symbol `%s'", this_module_name, symbol);
}
/*************************************************************************/
/*************************************************************************/
#if defined(GCC3_HACK)
# if defined(__sparc__)
# define IMPORT_FUNC(modulename, module, func) \
static void __dblocal_##func##_stub0(void) { \
void *ptr = NULL; \
if (!module) \
module = find_module(modulename); \
if (module) \
ptr = get_module_symbol(module, #func); \
if (!ptr) \
fatal_no_symbol(#func); \
__dblocal_##func = ptr; \
} \
static void *__dblocal_##func##_stub1(void) { \
__dblocal_##func##_stub0(); \
__builtin_return(__builtin_apply((void *)__dblocal_##func, \
__builtin_apply_args(), 64)); \
} \
static void __dblocal_##func##_stub(void) { \
(void) __builtin_apply((void *)__dblocal_##func##_stub1, \
__builtin_apply_args(), 64); \
asm("ld [%sp-128],%i0"); \
} \
typeof(func) *__dblocal_##func = (typeof(func) *) __dblocal_##func##_stub;
#elif defined(__POWERPC__)
# define IMPORT_FUNC(modulename, module, func) \
static void __dblocal_##func##_stub0(void) { \
void *ptr = NULL; \
if (!module) \
module = find_module(modulename); \
if (module) \
ptr = get_module_symbol(module, #func); \
if (!ptr) \
fatal_no_symbol(#func); \
__dblocal_##func = ptr; \
} \
static void __dblocal_##func##_stub(void) { \
asm("lwz r0,0(r1)\n \
stwu r0,-104(r1)\n \
stw r3,64(r1)\n \
stw r4,68(r1)\n \
stw r5,72(r1)\n \
stw r6,76(r1)\n \
stw r7,80(r1)\n \
stw r8,84(r1)\n \
stw r9,88(r1)\n \
stw r10,92(r1)\n \
mflr r0\n \
stw r0,100(r1)"); \
asm("mtctr %0\n \
bctrl\n \
lwz r10,92(r1)" : : "r" (__dblocal_##func##_stub0)); \
asm("stw %0,96(r1)" : : "r" (__dblocal_##func)); \
asm("lwz r3,64(r1)\n \
lwz r4,68(r1)\n \
lwz r5,72(r1)\n \
lwz r6,76(r1)\n \
lwz r7,80(r1)\n \
lwz r8,84(r1)\n \
lwz r9,88(r1)\n \
lwz r10,92(r1)\n \
lwz r11,96(r1)\n \
mtctr r11\n \
bctrl\n \
lwz r0,100(r1)\n \
mtlr r0\n \
mr r0,r3"); \
} \
typeof(func) *__dblocal_##func = (typeof(func) *) __dblocal_##func##_stub;
#else /* not SPARC and not PowerPC... must be our good old friend */
# define IMPORT_FUNC(modulename, module, func) \
static void __dblocal_##func##_stub0(void) { \
void *ptr = NULL; \
if (!module) \
module = find_module(modulename); \
if (module) \
ptr = get_module_symbol(module, #func); \
if (!ptr) \
fatal_no_symbol(#func); \
__dblocal_##func = ptr; \
} \
static void *__dblocal_##func##_stub(void) { \
__dblocal_##func##_stub0(); \
__builtin_return(__builtin_apply((void *)__dblocal_##func, \
__builtin_apply_args(), 64)); \
} \
typeof(func) *__dblocal_##func = (typeof(func) *) __dblocal_##func##_stub;
#endif /* to SPARC or not to SPARC */
#elif defined(__GNUC__)
#define IMPORT_FUNC(modulename, module, func) \
static void *__dblocal_##func##_stub(void) { \
void *ptr = NULL; \
if (!module) \
module = find_module(modulename); \
if (module) \
ptr = get_module_symbol(module, #func); \
if (!ptr) \
fatal_no_symbol(#func); \
__dblocal_##func = ptr; \
__builtin_return(__builtin_apply(ptr, __builtin_apply_args(), 64)); \
} \
typeof(func) *__dblocal_##func = (typeof(func) *) __dblocal_##func##_stub;
#elif defined(__INTEL_COMPILER)
volatile void *_fatal_no_symbol = (void *)fatal_no_symbol;
#define IMPORT_FUNC(modulename, module, func) \
static void __dblocal_##func##_stub(void) { \
asm(" movl "#module",%eax; \
testl %eax,%eax; \
jnz 1f; \
leal 8f,%eax; \
pushl %eax; \
call find_module; \
leal 4(%esp),%esp; \
movl %eax,"#module"; \
1: testl %eax,%eax; \
jz 2f; \
leal 9f,%edx; \
pushl %edx; \
pushl %eax; \
call get_module_symbol; \
leal 8(%esp),%esp; \
2: testl %eax,%eax; \
jnz 3f; \
leal 9f,%eax; \
pushl %eax; \
call *_fatal_no_symbol; \
leal 4(%esp),%esp; \
3: movl %eax,__dblocal_"#func"; \
movl %ebp,%esp; \
popl %ebp; \
jmp *%eax; \
8: .ascii \"" modulename "\\0\"; \
9: .ascii \""#func"\\0\" \
"); \
} \
typeof(func) *__dblocal_##func = (typeof(func) *) __dblocal_##func##_stub;
#else
#error IMPORT_FUNC not implemented for this compiler
#endif /* GCC3_HACK/etc */
#define IMPORT_VAR(modulename, module, var) \
static typeof(var) *__dblocal_##var##_ptr; \
typeof(var) __dblocal_get_##var(void) { \
if (!__dblocal_##var##_ptr) { \
if (!module) \
module = find_module(modulename); \
if (module) \
__dblocal_##var##_ptr = get_module_symbol(module, #var); \
if (!__dblocal_##var##_ptr) \
fatal_no_symbol(#var); \
} \
return *__dblocal_##var; \
}
#define IMPORT_VAR_MAYBE(modulename, module, var, default) \
static typeof(var) *__dblocal_##var##_ptr; \
typeof(var) __dblocal_get_##var(void) { \
if (!__dblocal_##var##_ptr) { \
if (!module) \
module = find_module(modulename); \
if (module) \
__dblocal_##var##_ptr = get_module_symbol(module, #var); \
} \
return __dblocal_##var##_ptr ? *__dblocal_##var##_ptr : default; \
}
/*************************************************************************/
IMPORT_VAR_MAYBE("chanserv/main", module_chanserv, CSMaxReg, CHANMAX_DEFAULT);
IMPORT_VAR_MAYBE("memoserv/main", module_memoserv, MSMaxMemos,MEMOMAX_DEFAULT);
IMPORT_FUNC("nickserv/main", module_nickserv, _get_ngi);
IMPORT_FUNC("nickserv/main", module_nickserv, _get_ngi_id);
IMPORT_FUNC("nickserv/main", module_nickserv, check_expire_nick);
IMPORT_FUNC("chanserv/main", module_chanserv, check_expire_channel);
IMPORT_FUNC("chanserv/main", module_chanserv, reset_levels);
IMPORT_FUNC("operserv/main", module_operserv, check_expire_maskdata);
IMPORT_FUNC("statserv/main", module_statserv, new_serverstats);
IMPORT_FUNC("statserv/main", module_statserv, free_serverstats);
/*************************************************************************/
/*************************************************************************/
static int do_unload_module(Module *mod)
{
if (mod == module_nickserv) {
module_nickserv = NULL;
__dblocal__get_ngi = (void *) __dblocal__get_ngi_stub;
__dblocal__get_ngi_id = (void *) __dblocal__get_ngi_id_stub;
} else if (mod == module_chanserv) {
module_chanserv = NULL;
__dblocal_CSMaxReg_ptr = NULL;
__dblocal_reset_levels = (void *) __dblocal_reset_levels_stub;
} else if (mod == module_memoserv) {
module_memoserv = NULL;
__dblocal_MSMaxMemos_ptr = NULL;
} else if (mod == module_statserv) {
module_statserv = NULL;
__dblocal_new_serverstats = (void *) __dblocal_new_serverstats_stub;
__dblocal_free_serverstats = (void *) __dblocal_free_serverstats_stub;
}
return 0;
}
/*************************************************************************/
/* `name' is the name of the calling module (used for errors) */
int init_extsyms(const char *name)
{
if (!add_callback(NULL, "unload module", do_unload_module))
return 0;
this_module_name = name;
return 1;
}
/*************************************************************************/
void exit_extsyms()
{
remove_callback(NULL, "unload module", do_unload_module);
}
/*************************************************************************/
syntax highlighted by Code2HTML, v. 0.9.1