| #ifndef APACHE_AP_HOOKS_H |
| #define APACHE_AP_HOOKS_H |
| |
| #define DECLARE_HOOK(ret,name,args) \ |
| typedef ret HOOK_##name args; \ |
| void ap_hook_##name(HOOK_##name *pf,const char * const *aszPre, \ |
| const char * const *aszSucc,int nOrder); \ |
| ret ap_run_##name args; \ |
| typedef struct _LINK_##name \ |
| { \ |
| HOOK_##name *pFunc; \ |
| const char *szName; \ |
| const char * const *aszPredecessors; \ |
| const char * const *aszSuccessors; \ |
| int nOrder; \ |
| } LINK_##name; |
| |
| #define HOOK_STRUCT(members) \ |
| static struct { members } _hooks; |
| |
| #define HOOK_LINK(name) \ |
| ap_array_header_t *link_##name; |
| |
| #define IMPLEMENT_HOOK_BASE(name) \ |
| void ap_hook_##name(HOOK_##name *pf,const char * const *aszPre, \ |
| const char * const *aszSucc,int nOrder) \ |
| { \ |
| LINK_##name *pHook; \ |
| if(!_hooks.link_##name) \ |
| { \ |
| _hooks.link_##name=ap_make_array(g_pHookPool,1,sizeof(LINK_##name)); \ |
| ap_hook_sort_register(#name,&_hooks.link_##name); \ |
| } \ |
| pHook=ap_push_array(_hooks.link_##name); \ |
| pHook->pFunc=pf; \ |
| pHook->aszPredecessors=aszPre; \ |
| pHook->aszSuccessors=aszSucc; \ |
| pHook->nOrder=nOrder; \ |
| pHook->szName=g_szCurrentHookName; \ |
| if(g_bDebugHooks) \ |
| ap_show_hook(#name,aszPre,aszSucc); \ |
| } |
| |
| /* RUN_ALL runs to the first one to return other than ok or decline |
| RUN_FIRST runs to the first one to return other than decline |
| VOID runs all |
| */ |
| |
| #define IMPLEMENT_HOOK_VOID(name,args_decl,args_use) \ |
| IMPLEMENT_HOOK_BASE(name) \ |
| void ap_run_##name args_decl \ |
| { \ |
| LINK_##name *pHook; \ |
| int n; \ |
| \ |
| if(!_hooks.link_##name) \ |
| return; \ |
| \ |
| pHook=(LINK_##name *)_hooks.link_##name->elts; \ |
| for(n=0 ; n < _hooks.link_##name->nelts ; ++n) \ |
| pHook[n].pFunc args_use; \ |
| } |
| |
| /* FIXME: note that this returns ok when nothing is run. I suspect it should |
| really return decline, but that breaks Apache currently - Ben |
| */ |
| #define IMPLEMENT_HOOK_RUN_ALL(ret,name,args_decl,args_use,ok,decline) \ |
| IMPLEMENT_HOOK_BASE(name) \ |
| ret ap_run_##name args_decl \ |
| { \ |
| LINK_##name *pHook; \ |
| int n; \ |
| ret rv; \ |
| \ |
| if(!_hooks.link_##name) \ |
| return ok; \ |
| \ |
| pHook=(LINK_##name *)_hooks.link_##name->elts; \ |
| for(n=0 ; n < _hooks.link_##name->nelts ; ++n) \ |
| { \ |
| rv=pHook[n].pFunc args_use; \ |
| \ |
| if(rv != ok && rv != decline) \ |
| return rv; \ |
| } \ |
| return ok; \ |
| } |
| |
| #define IMPLEMENT_HOOK_RUN_FIRST(ret,name,args_decl,args_use,decline) \ |
| IMPLEMENT_HOOK_BASE(name) \ |
| ret ap_run_##name args_decl \ |
| { \ |
| LINK_##name *pHook; \ |
| int n; \ |
| ret rv; \ |
| \ |
| if(!_hooks.link_##name) \ |
| return decline; \ |
| \ |
| pHook=(LINK_##name *)_hooks.link_##name->elts; \ |
| for(n=0 ; n < _hooks.link_##name->nelts ; ++n) \ |
| { \ |
| rv=pHook[n].pFunc args_use; \ |
| \ |
| if(rv != decline) \ |
| return rv; \ |
| } \ |
| return decline; \ |
| } |
| |
| /* Hook orderings */ |
| #define HOOK_REALLY_FIRST (-10) |
| #define HOOK_FIRST 0 |
| #define HOOK_MIDDLE 10 |
| #define HOOK_LAST 20 |
| #define HOOK_REALLY_LAST 30 |
| |
| extern ap_pool_t *g_pHookPool; |
| extern int g_bDebugHooks; |
| extern const char *g_szCurrentHookName; |
| |
| void ap_hook_sort_register(const char *szHookName, ap_array_header_t **aHooks); |
| void ap_sort_hooks(void); |
| void ap_show_hook(const char *szName,const char * const *aszPre, |
| const char * const *aszSucc); |
| |
| #endif /* ndef(AP_HOOKS_H) */ |