1
0
forked from mirrors/0ad

# SwEng: remove X-macros from app_hooks (confused static code analysis)

This was SVN commit r4372.
This commit is contained in:
janwas
2006-09-21 12:06:56 +00:00
parent d34ae19788
commit 05aadf1f12
2 changed files with 115 additions and 78 deletions
+65 -26
View File
@@ -39,7 +39,7 @@
// default implementations
//-----------------------------------------------------------------------------
static void override_gl_upload_caps()
static void def_override_gl_upload_caps()
{
if(gfx_card[0] == '\0')
debug_warn("gfx_detect must be called before ogl_tex_upload");
@@ -52,7 +52,7 @@ static void override_gl_upload_caps()
}
static const char* get_log_dir()
static const char* def_get_log_dir()
{
static char N_log_dir[PATH_MAX];
ONCE(\
@@ -92,7 +92,7 @@ static void cat_atow(FILE* out, const char* in_filename)
fclose(in);
}
static void bundle_logs(FILE* f)
static void def_bundle_logs(FILE* f)
{
// for user convenience, bundle all logs into this file:
char N_path[PATH_MAX];
@@ -109,25 +109,25 @@ static void bundle_logs(FILE* f)
}
static const wchar_t* translate(const wchar_t* text)
static const wchar_t* def_translate(const wchar_t* text)
{
return text;
}
static void translate_free(const wchar_t* UNUSED(text))
static void def_translate_free(const wchar_t* UNUSED(text))
{
// no-op - translate() doesn't own the pointer.
}
static void log(const wchar_t* text)
static void def_log(const wchar_t* text)
{
wprintf(text);
}
static ErrorReaction display_error(const wchar_t* UNUSED(text), uint UNUSED(flags))
static ErrorReaction def_display_error(const wchar_t* UNUSED(text), uint UNUSED(flags))
{
return ER_NOT_IMPLEMENTED;
}
@@ -135,7 +135,7 @@ static ErrorReaction display_error(const wchar_t* UNUSED(text), uint UNUSED(flag
//-----------------------------------------------------------------------------
// contains the current set of hooks. starts with the stub values and
// contains the current set of hooks. starts with the default values and
// may be changed via app_hooks_update.
//
// rationale: we don't ever need to switch "hook sets", so one global struct
@@ -143,30 +143,69 @@ static ErrorReaction display_error(const wchar_t* UNUSED(text), uint UNUSED(flag
// if anything was registered yet.
static AppHooks ah =
{
#define FUNC(ret, name, params, param_names, call_prefix) name,
#include "app_hooks.h"
#undef FUNC
// int dummy; used to terminate list, since last entry ended with ','.
0
def_override_gl_upload_caps,
def_get_log_dir,
def_bundle_logs,
def_translate,
def_translate_free,
def_log,
def_display_error
};
// register the specified hook function pointers. any of them that
// are non-zero override the previous function pointer value
// (these default to the stub hooks which are functional but basic).
void app_hooks_update(AppHooks* ah_)
void app_hooks_update(AppHooks* new_ah)
{
debug_assert(ah_);
debug_assert(new_ah);
// override members in <ah> if they are non-zero in <ah_>
// (otherwise, we stick with the defaults set above)
#define FUNC(ret, name, params, param_names, call_prefix) if(ah_->name) ah.name = ah_->name;
#include "app_hooks.h"
#undef FUNC
#define OVERRIDE_IF_NONZERO(HOOKNAME) if(new_ah->HOOKNAME) ah.HOOKNAME = new_ah->HOOKNAME;
OVERRIDE_IF_NONZERO(override_gl_upload_caps)
OVERRIDE_IF_NONZERO(get_log_dir)
OVERRIDE_IF_NONZERO(bundle_logs)
OVERRIDE_IF_NONZERO(translate)
OVERRIDE_IF_NONZERO(translate_free)
OVERRIDE_IF_NONZERO(log)
OVERRIDE_IF_NONZERO(display_error)
}
// trampolines used by lib code; they call the hooks or fall back to the
// default implementation if not set.
#define FUNC(ret, name, params, param_names, call_prefix) ret ah_##name params { call_prefix ah.name param_names; }
#include "app_hooks.h"
#undef FUNC
//-----------------------------------------------------------------------------
// trampoline implementations
// (boilerplate code; hides details of how to call the app hook)
//-----------------------------------------------------------------------------
void ah_override_gl_upload_caps(void)
{
ah.override_gl_upload_caps();
}
const char* ah_get_log_dir(void)
{
return ah.get_log_dir();
}
void ah_bundle_logs(FILE* f)
{
ah.bundle_logs(f);
}
const wchar_t* ah_translate(const wchar_t* text)
{
return ah.translate(text);
}
void ah_translate_free(const wchar_t* text)
{
ah.translate_free(text);
}
void ah_log(const wchar_t* text)
{
ah.log(text);
}
ErrorReaction ah_display_error(const wchar_t* text, uint flags)
{
return ah.display_error(text, flags);
}
+50 -52
View File
@@ -52,30 +52,43 @@ you need to implement a new version of some hooks, fill an
AppHooks struct with pointers to those functions (zero the rest),
and call app_hooks_update.
Adding New Functions
--------------------
Several steps are needed (see below for rationale):
0) HOOKNAME is the name of the desired procedure (e.g. "bundle_logs")
1) add a 'trampoline' (user visible function) declaration to this header
(typically named ah_HOOKNAME)
2) add the corresponding implementation, i.e. call to ah.HOOKNAME
3) add a default implementation of the new functionality
(typically named def_HOOKNAME)
4) add HOOKNAME member to struct AppHooks declaration
5) set HOOKNAME member to def_HOOKNAME in initialization of
'struct AppHooks ah'
6) add HOOKNAME to list in app_hooks_update code
Rationale
---------
While X-Macros would reduce the amount of work needed when adding new
functions, they confuse static code analysis and VisualAssist X
(the function definitions are not visible to them).
We prefer convenience during usage instead of in the rare cases
where new app hook functions are defined.
note: an X-Macro would define the app hook as such:
extern const wchar_t*, translate, (const wchar_t* text), (text), return)
.. and in its various invocations perform the above steps automatically.
*/
// X macros that define the individual hooks. All function pointers,
// struct contents, trampoline functions etc. are automatically
// generated from them to ease maintenance.
// When adding a new hook, you need only update this and write a
// default (stub) implementation.
//
// params:
// - ret: return value type
// - name: function name identifier
// - params: parameter declarations, used when declaring the function;
// enclosed in parentheses.
// - param_names: names of parameters, used when calling the function;
// enclosed in parentheses.
// - call_prefix: precedes the call to this function.
// must be (without quotes) '(void)' if ret is void, else 'return'.
// this is to allow generating trampoline functions with or without
// a return value.
#ifdef FUNC
#ifndef APP_HOOKS_H__
#define APP_HOOKS_H__
// for convenience; less confusing than FUNC(void, [..], (void))
#define VOID_FUNC(name, params, param_names)\
FUNC(void, name, params, param_names, (void))
// trampolines for user code to call the hooks. they encapsulate
// the details of how exactly to do this.
/**
* override default decision on using OpenGL extensions relating to
@@ -88,7 +101,7 @@ and call app_hooks_update.
* the default implementation works but is hardwired in code and therefore
* not expandable.
**/
VOID_FUNC(override_gl_upload_caps, (void), ())
extern void ah_override_gl_upload_caps(void);
/**
* return path to directory into which crash dumps should be written.
@@ -101,7 +114,7 @@ VOID_FUNC(override_gl_upload_caps, (void), ())
*
* @return full native path; must end with directory separator (e.g. '/').
**/
FUNC(const char*, get_log_dir, (void), (), return)
extern const char* ah_get_log_dir(void);
/**
* gather all app-related logs/information and write it to file.
@@ -113,7 +126,7 @@ FUNC(const char*, get_log_dir, (void), (), return)
*
* @param f file into which to write.
**/
VOID_FUNC(bundle_logs, (FILE* f), (f))
extern void ah_bundle_logs(FILE* f);
/**
* translate text to the current locale.
@@ -123,7 +136,7 @@ VOID_FUNC(bundle_logs, (FILE* f), (f))
*
* the default implementation just returns the pointer unchanged.
**/
FUNC(const wchar_t*, translate, (const wchar_t* text), (text), return)
extern const wchar_t* ah_translate(const wchar_t* text);
/**
* free text that was returned by translate.
@@ -132,7 +145,7 @@ FUNC(const wchar_t*, translate, (const wchar_t* text), (text), return)
*
* the default implementation does nothing.
**/
VOID_FUNC(translate_free, (const wchar_t* text), (text))
extern void ah_translate_free(const wchar_t* text);
/**
* write text to the app's log.
@@ -141,7 +154,7 @@ VOID_FUNC(translate_free, (const wchar_t* text), (text))
*
* the default implementation uses stdout.
**/
VOID_FUNC(log, (const wchar_t* text), (text))
extern void ah_log(const wchar_t* text);
/**
* display an error dialog, thus overriding sys_display_error.
@@ -153,30 +166,22 @@ VOID_FUNC(log, (const wchar_t* text), (text))
* the default implementation just returns ER_NOT_IMPLEMENTED, which
* causes the normal sys_display_error to be used.
**/
FUNC(ErrorReaction, display_error, (const wchar_t* text, uint flags), (text, flags), return)
extern ErrorReaction ah_display_error(const wchar_t* text, uint flags);
#undef VOID_FUNC
#endif // #ifdef FUNC
//-----------------------------------------------------------------------------
// normal header part
#ifndef APP_HOOKS_H__
#define APP_HOOKS_H__
/**
* holds a function pointer for each hook. passed to app_hooks_update.
* holds a function pointer (allowed to be NULL) for each hook.
* passed to app_hooks_update.
**/
struct AppHooks
{
#define FUNC(ret, name, params, param_names, call_prefix) ret (*name) params;
#include "app_hooks.h"
#undef FUNC
// used to safely terminate initializer list
int dummy;
void (*override_gl_upload_caps)(void);
const char* (*get_log_dir)(void);
void (*bundle_logs)(FILE* f);
const wchar_t* (*translate)(const wchar_t* text);
void (*translate_free)(const wchar_t* text);
void (*log)(const wchar_t* text);
ErrorReaction (*display_error)(const wchar_t* text, uint flags);
};
/**
@@ -188,11 +193,4 @@ struct AppHooks
**/
extern void app_hooks_update(AppHooks* ah);
// trampolines used by lib code to call the hooks. they encapsulate
// the details of how exactly to do this.
#define FUNC(ret, name, params, param_names, call_prefix) extern ret ah_##name params;
#include "app_hooks.h"
#undef FUNC
#endif // #ifndef APP_HOOKS_H__