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:
+65
-26
@@ -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
@@ -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__
|
||||
|
||||
Reference in New Issue
Block a user