You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@apr.apache.org by "William A. Rowe, Jr." <wr...@rowe-clan.net> on 2003/04/25 20:43:17 UTC
Creative solution to a lack of recursive #define's?
I'm attempting to come up with some more clever tracing semantics.
One thing I would like out of the user's foo_hook_method() invocation
is the stringized 'name' of their hook entry point. Seems I hit a wall.
Right now, apr_hooks uses the global 'apr_hook_debug_current'
pointer to track which module is registering hooks. Mostly painless
for the usual cases, since Apache sets up that pointer as it invokes
a module's register_hooks() entry point. But if a hook is registered
outside of that function, whoa boy.
Anyways, since the recursive #defines below don't work, and we don't
want the hook implementor to have to go through any 'extra' hoops,
does anyone have some thoughts on the fragment below for stringizing
the entry point 'pf's name?
#define APR_IMPLEMENT_HOOK_TRACE_PROTO(ns,name) \
#define ns##_hook_##name(pf, aszPre, aszSucc, nOrder) \
(ns##_hook_##name)(pf, aszPre, aszSucc, nOrder, #pf)
/** macro to declare the hook correctly */
#define APR_DECLARE_EXTERNAL_HOOK(ns,link,ret,name,args) \
typedef ret ns##_HOOK_##name##_t args; \
link##_DECLARE(void) ns##_hook_##name(ns##_HOOK_##name##_t *pf, \
const char * const *aszPre, \
const char * const *aszSucc, int nOrder\
const char * szFnName); \
link##_DECLARE(ret) ns##_run_##name args; \
APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name); \
APR_IMPLEMENT_HOOK_TRACE_PROTO(ns,name) \
typedef struct ns##_LINK_##name##_t \
{ \
ns##_HOOK_##name##_t *pFunc; \
const char *szName; \
const char * const *aszPredecessors; \
const char * const *aszSuccessors; \
int nOrder; \
} ns##_LINK_##name##_t;
Re: Creative solution to a lack of recursive #define's?
Posted by "William A. Rowe, Jr." <wr...@apache.org>.
At 11:11 AM 4/26/2003, Ben Laurie wrote:
>William A. Rowe, Jr. wrote:
>
>> I'm attempting to come up with some more clever tracing semantics.
>> One thing I would like out of the user's foo_hook_method() invocation
>> is the stringized 'name' of their hook entry point. Seems I hit a wall.
>>
>> Right now, apr_hooks uses the global 'apr_hook_debug_current'
>> pointer to track which module is registering hooks. Mostly painless
>> for the usual cases, since Apache sets up that pointer as it invokes
>> a module's register_hooks() entry point. But if a hook is registered
>> outside of that function, whoa boy.
>
>Why does thuis happen?
Well, it shouldn't on Apache. But hooks shouldn't be tied to Apache :-)
Besides, you know that foo registered the bar hook, but you don't
know the callback function name, which may be more useful.
>> #define APR_IMPLEMENT_HOOK_TRACE_PROTO(ns,name) \
>> #define ns##_hook_##name(pf, aszPre, aszSucc, nOrder) \
>> (ns##_hook_##name)(pf, aszPre, aszSucc, nOrder, #pf)
>
>Surely you can't do this???
No, but Mladen pointed out some tricks I will try ;-)
Bill
Re: Creative solution to a lack of recursive #define's?
Posted by Ben Laurie <be...@algroup.co.uk>.
William A. Rowe, Jr. wrote:
> I'm attempting to come up with some more clever tracing semantics.
> One thing I would like out of the user's foo_hook_method() invocation
> is the stringized 'name' of their hook entry point. Seems I hit a wall.
>
> Right now, apr_hooks uses the global 'apr_hook_debug_current'
> pointer to track which module is registering hooks. Mostly painless
> for the usual cases, since Apache sets up that pointer as it invokes
> a module's register_hooks() entry point. But if a hook is registered
> outside of that function, whoa boy.
Why does thuis happen?
> Anyways, since the recursive #defines below don't work, and we don't
> want the hook implementor to have to go through any 'extra' hoops,
> does anyone have some thoughts on the fragment below for stringizing
> the entry point 'pf's name?
>
> #define APR_IMPLEMENT_HOOK_TRACE_PROTO(ns,name) \
> #define ns##_hook_##name(pf, aszPre, aszSucc, nOrder) \
> (ns##_hook_##name)(pf, aszPre, aszSucc, nOrder, #pf)
Surely you can't do this???
Cheers,
Ben.
--
http://www.apache-ssl.org/ben.html http://www.thebunker.net/
"There is no limit to what a man can do or how far he can go if he
doesn't mind who gets the credit." - Robert Woodruff
Re: Creative solution to a lack of recursive #define's?
Posted by "William A. Rowe, Jr." <wr...@apache.org>.
If anyone is interested, I've attached the patch to hooks that provides
a trace callback... if I could resolve the issue described under this
message thread, and the fact that args_use is actually () wrapped
so that the patch attempts to invoke the cb with the args
(foo_run_something, NULL, 0, NULL, (arg1, arg2, arg3), NULL)
where the nested parens cause us to choke.
Bill
Re: Creative solution to a lack of recursive #define's?
Posted by "William A. Rowe, Jr." <wr...@rowe-clan.net>.
At 03:04 PM 4/25/2003, Jessie Oberreuter wrote:
>I'm not actually following what you are working on, but this may help.
>There is a "stringize" operator, the single hash, eg:
>
>#define DEF(a) const char* a=#a;
>
>DEF(ERROR_ARRAY_OVERRUN) =>
>const char* ERROR_ARRAY_OVERRUN="ERROR_ARRAY_OVERRUN";
>
> This is monumentally useful for building self-enumerating sets,
>hooks, and other such toys that are capable of reporting or perfoming
>lookups by their own names.
I'm familiar with it. The way we provide hooks, the user is responsible
for using two declaration macros, one for the prototype (e.g. in their .h)
and one for the implementation (e.g. in a .c)...
The one I'm most interested in is the declarator, study just this bit below;
#define APR_DECLARE_EXTERNAL_HOOK(ns,link,ret,name,args) \
typedef ret ns##_HOOK_##name##_t args; \
link##_DECLARE(void) ns##_hook_##name(ns##_HOOK_##name##_t *pf, \
const char * const *aszPre, \
const char * const *aszSucc, int nOrder, \
const char * szFnName); \
APR_DECLARE_EXTERNAL_HOOK(foo,FOO,dee_t*,twiddle,(dee_t *dum))
Gives you a function declaration;
FOO_DECLARE(dee_t *) foo_hook_twiddle(foo_HOOK_twiddle_t *pf,
const char * const *aszPre,
const char * const *aszSucc, int nOrder,
const char * szFnName);
What I really want is for the fifth arg above, szFnName, to actually be
the stringized version of the pf callback...
#define foo_hook_twiddle(pf, aszPre, aszSucc, nOrder) \
(foo_hook_twiddle)(pf, aszPre, aszSucc, nOrder, #pf)
However, using this declarator wrapper, it seems to be impossible to
provide this redefinition of foo_hook_twiddle without forcing the user
to do so themselves.
My question is how is it possible for our declarator macro to provide
this same functionallity, transparently, to any author who uses the
APR_DECLARE_EXTERNAL_HOOK macro?
Your solution works for that last define I illustrated above. But how is
it possible to provide this in terms of the declaration macro we use?
Bill
Re: Creative solution to a lack of recursive #define's?
Posted by Anthony Howe <ac...@snert.com>.
> Anyways, since the recursive #defines below don't work, and we don't
Standard C preprocessor is pretty limited. It was for this reason that
m4 was created. Maybe if you create an m4 template file then
preprocess that into a .c then compile it. Would that help?
--
Anthony C Howe +33 6 11 89 73 78
http://www.snert.com/ ICQ: 7116561 AIM: Sir Wumpus
"PAIN! Lots of pain!" - Wot
RE: Creative solution to a lack of recursive #define's?
Posted by Mladen Turk <mt...@inet.hr>.
> -----Original Message-----
> From: William A. Rowe, Jr.
>
> Anyways, since the recursive #defines below don't work, and
> we don't want the hook implementor to have to go through any
> 'extra' hoops, does anyone have some thoughts on the fragment
> below for stringizing the entry point 'pf's name?
>
> #define APR_IMPLEMENT_HOOK_TRACE_PROTO(ns,name) \
> #define ns##_hook_##name(pf, aszPre, aszSucc, nOrder) \
> (ns##_hook_##name)(pf, aszPre, aszSucc, nOrder, #pf)
>
I would create additional func that will return the function name.
Then you'll be sure that this function exists and can be called when
your trace function needs the name.
You may even create the expoted struct and return full info.
That is how most C++ runtime class name resolvers works.
> /** macro to declare the hook correctly */
> #define APR_DECLARE_EXTERNAL_HOOK(ns,link,ret,name,args) \
> typedef ret ns##_HOOK_##name##_t args; \
> link##_DECLARE(void) ns##_hook_##name(ns##_HOOK_##name##_t *pf, \
> const char * const *aszPre, \
> const char * const
> *aszSucc, int nOrder\
> const char * szFnName); \
link##_DECLARE(void) ns##_hook_##name(ns##_HOOK_##name##_t *pf, \
const char * const *aszPre, \
const char * const
*aszSucc, int nOrder); \
link##_DECLARE(const char *) ns##_get_name_##name();
> link##_DECLARE(ret) ns##_run_##name args; \
> APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name); \
> APR_IMPLEMENT_HOOK_TRACE_PROTO(ns,name) \
> typedef struct ns##_LINK_##name##_t \
> { \
> ns##_HOOK_##name##_t *pFunc; \
> const char *szName; \
> const char * const *aszPredecessors; \
> const char * const *aszSuccessors; \
> int nOrder; \
> } ns##_LINK_##name##_t;
>
Then add the implementation like:
link##_DECLARE(const char *) ns##_get_name_##name() { \
return #name; }
Or even better, create the runtime info struct, implement it and return
that struct when needed.
typedef struct {
const char *szName;
const char * const *aszPredecessors;
const char * const *aszSuccessors;
int nOrder;
} apr_runtime_hook_info_t;
APR_IMPLEMENT_HOOK_TRACE_PROTO(ns,name) \
typedef struct ns##_LINK_##name##_t \
{ \
apr_runtime_hook_info info; \
ns##_HOOK_##name##_t *pFunc; \
} ns##_LINK_##name##_t; \
link##_DECLARE apr_runtime_hook_info ns##_INFO_##name##_info = { \
#name, NULL, NULL, 0 }; \
link##_DECLARE(const apr_runtime_hook_info *) ns##_get_info_##name() { \
return &ns##_INFO_##name##_info; }
...
MT.
Re: Creative solution to a lack of recursive #define's?
Posted by Jessie Oberreuter <jo...@moselle.com>.
I'm not actually following what you are working on, but this may help.
There is a "stringize" operator, the single hash, eg:
#define DEF(a) const char* a=#a;
DEF(ERROR_ARRAY_OVERRUN) =>
const char* ERROR_ARRAY_OVERRUN="ERROR_ARRAY_OVERRUN";
This is monumentally useful for building self-enumerating sets,
hooks, and other such toys that are capable of reporting or perfoming
lookups by their own names.
On Fri, 25 Apr 2003, William A. Rowe, Jr. wrote:
> I'm attempting to come up with some more clever tracing semantics.
> One thing I would like out of the user's foo_hook_method() invocation
> is the stringized 'name' of their hook entry point. Seems I hit a wall.
>
> Right now, apr_hooks uses the global 'apr_hook_debug_current'
> pointer to track which module is registering hooks. Mostly painless
> for the usual cases, since Apache sets up that pointer as it invokes
> a module's register_hooks() entry point. But if a hook is registered
> outside of that function, whoa boy.
>
> Anyways, since the recursive #defines below don't work, and we don't
> want the hook implementor to have to go through any 'extra' hoops,
> does anyone have some thoughts on the fragment below for stringizing
> the entry point 'pf's name?
>
> #define APR_IMPLEMENT_HOOK_TRACE_PROTO(ns,name) \
> #define ns##_hook_##name(pf, aszPre, aszSucc, nOrder) \
> (ns##_hook_##name)(pf, aszPre, aszSucc, nOrder, #pf)
>
> /** macro to declare the hook correctly */
> #define APR_DECLARE_EXTERNAL_HOOK(ns,link,ret,name,args) \
> typedef ret ns##_HOOK_##name##_t args; \
> link##_DECLARE(void) ns##_hook_##name(ns##_HOOK_##name##_t *pf, \
> const char * const *aszPre, \
> const char * const *aszSucc, int nOrder\
> const char * szFnName); \
> link##_DECLARE(ret) ns##_run_##name args; \
> APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name); \
> APR_IMPLEMENT_HOOK_TRACE_PROTO(ns,name) \
> typedef struct ns##_LINK_##name##_t \
> { \
> ns##_HOOK_##name##_t *pFunc; \
> const char *szName; \
> const char * const *aszPredecessors; \
> const char * const *aszSuccessors; \
> int nOrder; \
> } ns##_LINK_##name##_t;
>
>
>