Interface changes: no more KIND ints, all context.name strings now;

Initial version of Event system


git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@1286 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
avolkov
2003-10-27 04:50:06 +00:00
parent a1656ce168
commit a6e4933338
8 changed files with 900 additions and 149 deletions
+130 -36
View File
@@ -26,6 +26,7 @@
#include "cdpint.h" #include "cdpint.h"
#include "cdpmod.h" #include "cdpmod.h"
#include "uio.h" #include "uio.h"
#include "uqmversion.h"
#ifdef WIN32 #ifdef WIN32
# include "windl.h" # include "windl.h"
#else #else
@@ -35,21 +36,50 @@
#define MAX_CDPS 63 #define MAX_CDPS 63
#define CDPDIR "cdps" #define CDPDIR "cdps"
// internal adl module representation // internal CDP module representation
// cdp_Module will be cast to and from this
struct cdp_Module struct cdp_Module
{ {
bool used; // used at least once indicator bool builtin; // used at least once indicator
void* hmodule; // loaded module handle bool used; // used at least once indicator
uint32 refcount; // reference count void* hmodule; // loaded module handle
uint32 refcount; // reference count
cdp_ModuleInfo* info; // cdp exported info cdp_ModuleInfo* info; // cdp exported info
}; };
// Kernel module info
// not a real module, and not loadable either
// this just provides information to other modules
cdp_ModuleInfo cdp_kernel_info =
{
sizeof (cdp_ModuleInfo),
CDPAPI_VERSION, // API version we are using
UQM_MAJOR_VERSION, UQM_MINOR_VERSION,
UQM_MAJOR_VERSION, UQM_MINOR_VERSION,
CDP_MODINFO_RESERVED1,
"UQM", // CDP context cannonical name
"UQM Kernel", // CDP mod name
# define S(i) #i
// CDP mod version
S(UQM_MAJOR_VERSION) "." S(UQM_MINOR_VERSION) UQM_EXTRA_VERSION,
# undef S
"UQM Team", // CDP mod author
"http://sc2.sf.net", // CDP mod URL
"Eternal doctrine executor", // CDP mod comment
CDP_MODINFO_RESERVED2,
NULL, NULL // no entrypoints defined/needed
};
static cdp_Module cdp_modules[MAX_CDPS + 1] =
{
{true, true, NULL, 1, &cdp_kernel_info},
{false, false, NULL, 0, NULL} // term
};
extern uio_DirHandle *cdpDir; extern uio_DirHandle *cdpDir;
static bool cdp_inited = false; static bool cdp_inited = false;
static cdp_Module cdp_modules[MAX_CDPS + 1];
static cdp_Error cdp_last_error = CDPERR_NONE; static cdp_Error cdp_last_error = CDPERR_NONE;
static char cdp_path[PATH_MAX] = ""; static char cdp_path[PATH_MAX] = "";
@@ -64,13 +94,25 @@ cdp_GetError (void)
bool bool
cdp_Init (void) cdp_Init (void)
{ {
int i;
void* hkernel;
if (cdp_inited) if (cdp_inited)
{ {
fprintf (stderr, "cdp_Init(): called when already inited\n"); fprintf (stderr, "cdp_Init(): called when already inited\n");
return true; return true;
} }
memset (cdp_modules, 0, sizeof cdp_modules); // preprocess built-in modules
hkernel = dlopen (NULL, RTLD_LAZY);
for (i = 0; cdp_modules[i].builtin; ++i)
cdp_modules[i].hmodule = hkernel;
// clear the rest
//memset (cdp_modules + i, 0,
// sizeof (cdp_modules) - sizeof (cdp_Module) * i);
//strcpy (cdp_path, cdpDir->path); //strcpy (cdp_path, cdpDir->path);
cdp_InitApi (); cdp_InitApi ();
cdp_inited = true; cdp_inited = true;
@@ -94,6 +136,7 @@ cdp_Uninit (void)
cdp_Module* cdp_Module*
cdp_LoadModule (const char* modname) cdp_LoadModule (const char* modname)
// special value for modname: NULL - refers to kernel (UQM exe)
{ {
void* mod; void* mod;
char modpath[PATH_MAX]; char modpath[PATH_MAX];
@@ -104,6 +147,9 @@ cdp_LoadModule (const char* modname)
cdp_Module* newslot = 0; cdp_Module* newslot = 0;
cdp_Itf* ihost; cdp_Itf* ihost;
if (modname == NULL)
return cdp_modules;
if (!cdp_inited) if (!cdp_inited)
{ {
fprintf (stderr, "cdp_LoadModule(): called when not inited\n"); fprintf (stderr, "cdp_LoadModule(): called when not inited\n");
@@ -173,24 +219,33 @@ cdp_LoadModule (const char* modname)
return NULL; return NULL;
} }
if (!info->module_init ((cdp_Itf_Host*)ihost)) if (!newslot)
{
newslot = cdp;
newslot->used = true;
// make next one a term
cdp[1].builtin = false;
cdp[1].used = false;
cdp[1].hmodule = NULL;
cdp[1].refcount = 0;
}
newslot->hmodule = mod;
newslot->refcount = 1;
newslot->info = info;
if (!info->module_init (newslot, (cdp_Itf_Host*)ihost))
{ {
fprintf (stderr, "cdp_LoadModule(): " fprintf (stderr, "cdp_LoadModule(): "
"CDP %s failed to init\n", "CDP %s failed to init\n",
modname); modname);
dlclose (mod); dlclose (mod);
newslot->hmodule = NULL;
newslot->info = NULL;
newslot->refcount = 0;
cdp_last_error = CDPERR_INIT_FAILED; cdp_last_error = CDPERR_INIT_FAILED;
return NULL; return NULL;
} }
if (!newslot)
{
newslot = cdp;
newslot->used = true;
}
newslot->hmodule = mod;
newslot->refcount = 1;
newslot->info = info;
return newslot; return newslot;
} }
@@ -210,7 +265,7 @@ cdp_FreeModule (cdp_Module* module)
{ {
cdp_Module* modslot = cdp_CheckModule (module); cdp_Module* modslot = cdp_CheckModule (module);
if (!modslot) if (!modslot || modslot->builtin)
return; return;
modslot->refcount--; modslot->refcount--;
@@ -227,13 +282,38 @@ cdp_FreeModule (cdp_Module* module)
} }
const char* const char*
cdp_GetModuleName (cdp_Module* module) cdp_GetModuleContext (cdp_Module* module, bool bMetaString)
{ {
cdp_Module* modslot = cdp_CheckModule (module); cdp_Module* modslot = cdp_CheckModule (module);
if (!modslot) if (bMetaString)
return "(Error)"; {
if (!modslot->info->name) if (!modslot)
return "(Null)"; return "(Error)";
if (!modslot->info->context_name)
return "(Null)";
}
else if (!modslot)
{
return NULL;
}
return modslot->info->context_name;
}
const char*
cdp_GetModuleName (cdp_Module* module, bool bMetaString)
{
cdp_Module* modslot = cdp_CheckModule (module);
if (bMetaString)
{
if (!modslot)
return "(Error)";
if (!modslot->info->name)
return "(Null)";
}
else if (!modslot)
{
return NULL;
}
return modslot->info->name; return modslot->info->name;
} }
@@ -247,24 +327,38 @@ cdp_GetModuleVersion (cdp_Module* module)
} }
const char* const char*
cdp_GetModuleVersionString (cdp_Module* module) cdp_GetModuleVersionString (cdp_Module* module, bool bMetaString)
{ {
cdp_Module* modslot = cdp_CheckModule (module); cdp_Module* modslot = cdp_CheckModule (module);
if (!modslot) if (bMetaString)
return "(Error)"; {
if (!modslot->info->ver_string) if (!modslot)
return "(Null)"; return "(Error)";
if (!modslot->info->ver_string)
return "(Null)";
}
else if (!modslot)
{
return NULL;
}
return modslot->info->ver_string; return modslot->info->ver_string;
} }
const char* const char*
cdp_GetModuleComment (cdp_Module* module) cdp_GetModuleComment (cdp_Module* module, bool bMetaString)
{ {
cdp_Module* modslot = cdp_CheckModule (module); cdp_Module* modslot = cdp_CheckModule (module);
if (!modslot) if (bMetaString)
return "(Error)"; {
if (!modslot->info->comments) if (!modslot)
return "(Null)"; return "(Error)";
if (!modslot->info->comments)
return "(Null)";
}
else if (!modslot)
{
return NULL;
}
return modslot->info->comments; return modslot->info->comments;
} }
@@ -309,9 +403,9 @@ cdp_LoadAllModules (void)
{ {
nummods++; nummods++;
fprintf (stderr, "\tloaded CDP: %s v%s (%s)\n", fprintf (stderr, "\tloaded CDP: %s v%s (%s)\n",
cdp_GetModuleName (mod), cdp_GetModuleName (mod, true),
cdp_GetModuleVersionString (mod), cdp_GetModuleVersionString (mod, true),
cdp_GetModuleComment (mod)); cdp_GetModuleComment (mod, true));
} }
else else
{ {
@@ -337,7 +431,7 @@ cdp_FreeAllModules (void)
for (cdp = cdp_modules; cdp->used; ++cdp) for (cdp = cdp_modules; cdp->used; ++cdp)
{ {
if (cdp->hmodule) if (!cdp->builtin && cdp->hmodule)
cdp_FreeModule (cdp); cdp_FreeModule (cdp);
} }
} }
+7 -3
View File
@@ -32,10 +32,14 @@ void cdp_Uninit (void);
cdp_Error cdp_GetError (void); cdp_Error cdp_GetError (void);
cdp_Module* cdp_LoadModule (const char* modname); cdp_Module* cdp_LoadModule (const char* modname);
void cdp_FreeModule (cdp_Module* module); void cdp_FreeModule (cdp_Module* module);
const char* cdp_GetModuleName (cdp_Module* module); // in the following calls when bMetaString is set
// function will never return a NULL, instead it will
// return a valid string -- error meta-string
const char* cdp_GetModuleContext (cdp_Module* module, bool bMetaString);
const char* cdp_GetModuleName (cdp_Module* module, bool bMetaString);
uint32 cdp_GetModuleVersion (cdp_Module* module); uint32 cdp_GetModuleVersion (cdp_Module* module);
const char* cdp_GetModuleVersionString (cdp_Module* module); const char* cdp_GetModuleVersionString (cdp_Module* module, bool bMetaString);
const char* cdp_GetModuleComment (cdp_Module* module); const char* cdp_GetModuleComment (cdp_Module* module, bool bMetaString);
int cdp_LoadAllModules (void); int cdp_LoadAllModules (void);
void cdp_FreeAllModules (void); void cdp_FreeAllModules (void);
+4 -2
View File
@@ -28,9 +28,11 @@
// CDP IO Interface entry points // CDP IO Interface entry points
typedef struct typedef struct
{ {
uio_Stream* (* fopen) (uio_DirHandle *dir, const char *path, const char *mode); uio_Stream* (* fopen) (uio_DirHandle *dir, const char *path,
const char *mode);
int (* fclose) (uio_Stream *stream); int (* fclose) (uio_Stream *stream);
size_t (* fread) (void *buf, size_t size, size_t nmemb, uio_Stream *stream); size_t (* fread) (void *buf, size_t size, size_t nmemb,
uio_Stream *stream);
size_t (* fwrite) (const void *buf, size_t size, size_t nmemb, size_t (* fwrite) (const void *buf, size_t size, size_t nmemb,
uio_Stream *stream); uio_Stream *stream);
int (* fseek) (uio_Stream *stream, long offset, int whence); int (* fseek) (uio_Stream *stream, long offset, int whence);
+649 -70
View File
@@ -25,18 +25,33 @@
#include "cdpint.h" #include "cdpint.h"
#include "uqmversion.h" #include "uqmversion.h"
#define MAX_REG_ITFS 255 #define MAX_REG_ITFS 255
#define MAX_REG_EVENTS 1023
static cdp_Error cdp_api_error = CDPERR_NONE; static cdp_Error cdp_api_error = CDPERR_NONE;
static uint32 cdp_Host_GetApiVersion (void); static uint32 cdp_Host_GetApiVersion (void);
static uint32 cdp_Host_GetVersion (void); static uint32 cdp_Host_GetVersion (void);
static cdp_Error cdp_Host_GetApiError (void); static cdp_Error cdp_Host_GetApiError (void);
static cdp_Itf* cdp_Host_GetItf (cdp_ItfKind); static cdp_Itf* cdp_Host_GetItf (const char* name);
static cdp_RegItf* cdp_Host_RegisterItf (cdp_ItfKind, static bool cdp_Host_GetItfs (cdp_ItfDef* defs);
static cdp_ItfReg* cdp_Host_RegisterItf (const char* name,
cdp_ApiVersion ver_from, cdp_ApiVersion ver_to, cdp_ApiVersion ver_from, cdp_ApiVersion ver_to,
cdp_Itf*, cdp_Module*); cdp_Itf*, cdp_Module*);
static void cdp_Host_UnregisterItf (cdp_RegItf*); static void cdp_Host_UnregisterItf (cdp_ItfReg*);
static bool cdp_Host_RegisterItfs (cdp_ItfDef* defs, cdp_Module*);
static void cdp_Host_UnregisterItfs (cdp_ItfDef* defs);
static cdp_Event cdp_Host_GetEvent (const char* name);
static bool cdp_Host_GetEvents (cdp_EventDef* defs);
static cdp_EventReg* cdp_Host_RegisterEvent (const char* name, cdp_Module*);
static void cdp_Host_UnregisterEvent (cdp_EventReg*);
static bool cdp_Host_RegisterEvents (cdp_EventDef* defs, cdp_Module*);
static void cdp_Host_UnregisterEvents (cdp_EventDef* defs);
static bool cdp_Host_SubscribeEvent (cdp_Event, cdp_EventProc, cdp_Module*);
static void cdp_Host_UnsubscribeEvent (cdp_Event, cdp_EventProc);
static bool cdp_Host_SubscribeEvents (cdp_EventDef* defs, cdp_Module*);
static void cdp_Host_UnsubscribeEvents (cdp_EventDef* defs);
static cdp_EventResult cdp_Host_FireEvent (cdp_EventReg*, uint32, void*);
// Interfaces // Interfaces
cdp_Itf_HostVtbl_v1 cdp_host_itf_v1 = cdp_Itf_HostVtbl_v1 cdp_host_itf_v1 =
@@ -45,8 +60,22 @@ cdp_Itf_HostVtbl_v1 cdp_host_itf_v1 =
cdp_Host_GetVersion, cdp_Host_GetVersion,
cdp_Host_GetApiError, cdp_Host_GetApiError,
cdp_Host_GetItf, cdp_Host_GetItf,
cdp_Host_GetItfs,
cdp_Host_RegisterItf, cdp_Host_RegisterItf,
cdp_Host_UnregisterItf, cdp_Host_UnregisterItf,
cdp_Host_RegisterItfs,
cdp_Host_UnregisterItfs,
cdp_Host_GetEvent,
cdp_Host_GetEvents,
cdp_Host_RegisterEvent,
cdp_Host_UnregisterEvent,
cdp_Host_RegisterEvents,
cdp_Host_UnregisterEvents,
cdp_Host_SubscribeEvent,
cdp_Host_UnsubscribeEvent,
cdp_Host_SubscribeEvents,
cdp_Host_UnsubscribeEvents,
cdp_Host_FireEvent,
}; };
cdp_Itf_MemoryVtbl_v1 cdp_memory_itf_v1 = cdp_Itf_MemoryVtbl_v1 cdp_memory_itf_v1 =
@@ -84,23 +113,24 @@ cdp_Itf_VideoVtbl_v1 cdp_video_itf_v1 =
VideoDecoder_Lookup, VideoDecoder_Lookup,
}; };
struct cdp_RegItf // the actual interface registration struct/handle
struct cdp_ItfReg
{ {
bool builtin; bool builtin;
bool used; bool used;
cdp_ItfKind kind; const char* name;
cdp_ApiVersion ver_from; cdp_ApiVersion ver_from;
cdp_ApiVersion ver_to; cdp_ApiVersion ver_to;
cdp_Itf* itfvtbl; cdp_Itf* itfvtbl;
cdp_Module* module; cdp_Module* module;
}; };
#define CDP_DECLARE_ITF(k,vf,vt,vtbl) \ #define CDP_DECLARE_ITF(kind,vf,vt,vtbl) \
{true, true, CDPITF_KIND_##k, \ {true, true, CDPITF_KIND_##kind, \
CDPAPI_VERSION_##vf, CDPAPI_VERSION_##vt, vtbl, NULL} CDPAPI_VERSION_##vf, CDPAPI_VERSION_##vt, vtbl, NULL}
// Built-in interfaces + space for loadable // Built-in interfaces + space for loadable
cdp_RegItf cdp_itfs[MAX_REG_ITFS + 1] = cdp_ItfReg cdp_itfs[MAX_REG_ITFS + 1] =
{ {
CDP_DECLARE_ITF (HOST, 1, 1, &cdp_host_itf_v1), CDP_DECLARE_ITF (HOST, 1, 1, &cdp_host_itf_v1),
CDP_DECLARE_ITF (MEMORY, 1, 1, &cdp_memory_itf_v1), CDP_DECLARE_ITF (MEMORY, 1, 1, &cdp_memory_itf_v1),
@@ -109,7 +139,43 @@ cdp_RegItf cdp_itfs[MAX_REG_ITFS + 1] =
CDP_DECLARE_ITF (VIDEO, 1, 1, &cdp_video_itf_v1), CDP_DECLARE_ITF (VIDEO, 1, 1, &cdp_video_itf_v1),
// TODO: put newly defined built-in interfaces here // TODO: put newly defined built-in interfaces here
{false, false, CDPITF_KIND_INVALID, 0, 0, NULL} // term {false, false, "", 0, 0, NULL} // term
};
// event bind descriptor
typedef struct
{
cdp_EventProc proc;
cdp_Module* module;
} cdp_EventBind;
#define EVENT_BIND_GROW 16
// the actual event registration struct/handle
struct cdp_EventReg
{
bool builtin;
bool used;
const char* name;
cdp_EventBind* binds;
uint32 bindslots;
cdp_Module* module;
};
#define CDP_DECLARE_EVENT(name) \
{true, true, "UQM." #name, NULL, 0, NULL}
// Built-in events + space for loadable
// a cdp_Event handle is an index into this array
cdp_EventReg cdp_evts[MAX_REG_EVENTS + 1] =
{
// sample - no real events defined yet
CDP_DECLARE_EVENT (PlanetSide.TouchDown),
CDP_DECLARE_EVENT (PlanetSide.LiftOff),
// TODO: put newly defined built-in events here
{false, false, "", NULL, 0, NULL} // term
}; };
cdp_Error cdp_Error
@@ -123,14 +189,34 @@ cdp_GetApiError (void)
bool bool
cdp_InitApi (void) cdp_InitApi (void)
{ {
// TODO: add whatever init code is necessary int i;
cdp_Module* kernel;
// preprocess built-in itfs
kernel = cdp_LoadModule (NULL);
for (i = 0; cdp_itfs[i].builtin; ++i)
{
cdp_itfs[i].module = kernel;
}
// clear the rest
//memset (cdp_itfs + i, 0,
// sizeof (cdp_itfs) - sizeof (cdp_ItfReg) * i);
for (i = 0; cdp_evts[i].builtin; ++i)
{
cdp_evts[i].module = kernel;
cdp_evts[i].bindslots = 0;
cdp_evts[i].binds = NULL;
}
return true; return true;
} }
void void
cdp_UninitApi (void) cdp_UninitApi (void)
{ {
cdp_RegItf* itf; cdp_ItfReg* itf;
// unregister custom interfaces // unregister custom interfaces
for (itf = cdp_itfs; itf->used; ++itf) for (itf = cdp_itfs; itf->used; ++itf)
@@ -138,31 +224,15 @@ cdp_UninitApi (void)
if (!itf->builtin) if (!itf->builtin)
{ {
itf->used = false; itf->used = false;
itf->kind = CDPITF_KIND_INVALID; if (itf->name)
HFree ((void*) itf->name);
itf->name = NULL;
itf->itfvtbl = NULL; itf->itfvtbl = NULL;
itf->module = NULL;
} }
} }
} }
cdp_Itf*
cdp_GetInterface (cdp_ItfKind itf_kind, cdp_ApiVersion api_ver)
{
cdp_RegItf* itf;
for (itf = cdp_itfs; itf->used &&
(itf->kind != itf_kind ||
api_ver < itf->ver_from || api_ver > itf->ver_to);
itf++)
;
if (!itf->kind)
{
cdp_api_error = CDPERR_NO_ITF;
return NULL;
}
return itf->itfvtbl;
}
static uint32 static uint32
cdp_Host_GetApiVersion (void) cdp_Host_GetApiVersion (void)
{ {
@@ -181,32 +251,125 @@ cdp_Host_GetApiError (void)
return cdp_GetApiError (); return cdp_GetApiError ();
} }
static cdp_Itf* static char*
cdp_Host_GetItf (cdp_ItfKind itf_kind) cdp_MakeContextName (const char* ctx, const char* name)
{ {
return cdp_GetInterface (itf_kind, CDPAPI_VERSION_1); int namelen;
char* id_name;
namelen = strlen(ctx) + strlen(name) + 2;
id_name = HMalloc (namelen);
strcpy(id_name, ctx);
strcat(id_name, ".");
strcat(id_name, name);
return id_name;
} }
static cdp_RegItf* /***********************************************************
cdp_Host_RegisterItf (cdp_ItfKind itf_kind, cdp_ApiVersion ver_from, * Interface system *
cdp_ApiVersion ver_to, cdp_Itf* itfvtbl, cdp_Module* module) ***********************************************************/
{
cdp_RegItf* regitf;
cdp_RegItf* newslot = NULL;
if (!module) cdp_ItfReg*
cdp_GetInterfaceReg (const char* name, cdp_ApiVersion api_ver)
{
cdp_ItfReg* itf;
for (itf = cdp_itfs; itf->used &&
(!itf->name || stricmp(itf->name, name) != 0 ||
api_ver < itf->ver_from || api_ver > itf->ver_to);
itf++)
;
if (!itf->name)
{
cdp_api_error = CDPERR_NO_ITF;
return NULL;
}
return itf;
}
cdp_Itf*
cdp_GetInterface (const char* name, cdp_ApiVersion api_ver)
{
cdp_ItfReg* reg;
reg = cdp_GetInterfaceReg (name, api_ver);
return reg ? reg->itfvtbl : NULL;
}
static cdp_Itf*
cdp_Host_GetItf (const char* name)
{
return cdp_GetInterface (name, CDPAPI_VERSION_1);
}
static bool
cdp_Host_GetItfs (cdp_ItfDef* defs)
{
cdp_ItfDef* def;
cdp_ItfReg* reg;
int errors = 0;
for (def = defs; def->name; ++def)
{
// registration handle is not returned
def->reg = NULL;
reg = cdp_GetInterfaceReg (def->name, CDPAPI_VERSION_1);
if (reg)
{
def->itf = reg->itfvtbl;
def->name = reg->name; // set to cannonical name
def->ver_from = reg->ver_from;
def->ver_to = reg->ver_to;
def->module = reg->module;
}
else
{
def->itf = NULL;
def->module = NULL;
def->ver_from = 0;
def->ver_to = 0;
++errors;
}
}
return !errors;
}
static cdp_ItfReg*
cdp_Host_RegisterItf (const char* name, cdp_ApiVersion ver_from,
cdp_ApiVersion ver_to, cdp_Itf* itfvtbl,
cdp_Module* owner)
{
cdp_ItfReg* itfreg;
cdp_ItfReg* newslot = NULL;
char* id_name;
const char* ctx;
if (!owner)
{ {
fprintf (stderr, "cdp_Host_RegisterItf(): " fprintf (stderr, "cdp_Host_RegisterItf(): "
"No module info supplied\n"); "No owner info supplied\n");
//return NULL; //return NULL;
} }
if (!itf_kind || !itfvtbl) if (!name || !*name || !itfvtbl)
{ {
fprintf (stderr, "cdp_Host_RegisterItf(): " fprintf (stderr, "cdp_Host_RegisterItf(): "
"Null or invalid interface (from %s)\n", "Null or invalid interface (from %s)\n",
cdp_GetModuleName (module)); cdp_GetModuleName (owner, true));
return NULL; return NULL;
} }
ctx = cdp_GetModuleContext (owner, false);
if (!ctx)
{
fprintf (stderr, "cdp_Host_RegisterItf(): "
"Null or invalid context (from %s)\n",
cdp_GetModuleName (owner, true));
return NULL;
}
// TODO: review version policy (below) // TODO: review version policy (below)
// enforce version policy and do not allow obsolete interfaces // enforce version policy and do not allow obsolete interfaces
// POLICY: all modules MUST be aware of recent API changes and will not // POLICY: all modules MUST be aware of recent API changes and will not
@@ -217,68 +380,484 @@ cdp_Host_RegisterItf (cdp_ItfKind itf_kind, cdp_ApiVersion ver_from,
if (ver_to < CDPAPI_VERSION_MIN) if (ver_to < CDPAPI_VERSION_MIN)
{ {
fprintf (stderr, "cdp_Host_RegisterItf(): " fprintf (stderr, "cdp_Host_RegisterItf(): "
"Obsolete interface 0x%08x (from %s)\n", "Obsolete interface %s (from %s)\n",
itf_kind, cdp_GetModuleName (module)); name, cdp_GetModuleName (owner, true));
return NULL; return NULL;
} }
// check if extension already registered id_name = cdp_MakeContextName (ctx, name);
for (regitf = cdp_itfs; regitf->used &&
(regitf->kind != itf_kind || // check if interface already registered
ver_from < regitf->ver_from || ver_to > regitf->ver_to); for (itfreg = cdp_itfs; itfreg->used &&
++regitf) (!itfreg->name || stricmp(itfreg->name, id_name) != 0 ||
ver_from < itfreg->ver_from || ver_to > itfreg->ver_to);
++itfreg)
{ {
// and pick up an empty slot (where available) // and pick up an empty slot (where available)
if (!newslot && !regitf->kind) if (!newslot && !itfreg->name)
newslot = regitf; newslot = itfreg;
} }
if (regitf >= cdp_itfs + MAX_REG_ITFS) if (itfreg >= cdp_itfs + MAX_REG_ITFS)
{ {
fprintf (stderr, "cdp_Host_RegisterItf(): " fprintf (stderr, "cdp_Host_RegisterItf(): "
"Interfaces limit reached\n"); "Interfaces limit reached\n");
HFree (id_name);
return NULL; return NULL;
} }
else if (regitf->kind) else if (itfreg->name)
{ {
fprintf (stderr, "cdp_Host_RegisterItf(): " fprintf (stderr, "cdp_Host_RegisterItf(): "
"interface 0x%08x already registered for these versions, " "Interface %s already registered for these versions, "
"%s denied\n", "%s denied\n",
itf_kind, cdp_GetModuleName (module)); name, cdp_GetModuleName (owner, true));
HFree (id_name);
return NULL; return NULL;
} }
if (!newslot) if (!newslot)
{ {
newslot = regitf; newslot = itfreg;
newslot->used = true; newslot->used = true;
// make next one a term // make next one a term
regitf[1].builtin = false; itfreg[1].builtin = false;
regitf[1].used = false; itfreg[1].used = false;
regitf[1].kind = CDPITF_KIND_INVALID; itfreg[1].name = NULL;
regitf[1].itfvtbl = NULL; itfreg[1].itfvtbl = NULL;
} }
newslot->kind = itf_kind; newslot->name = id_name;
newslot->ver_from = ver_from; newslot->ver_from = ver_from;
newslot->ver_to = ver_to; newslot->ver_to = ver_to;
newslot->itfvtbl = itfvtbl; newslot->itfvtbl = itfvtbl;
newslot->module = module; newslot->module = owner;
return newslot; return newslot;
} }
static void static void
cdp_Host_UnregisterItf (cdp_RegItf* regitf) cdp_Host_UnregisterItf (cdp_ItfReg* itfreg)
{ {
if (regitf < cdp_itfs || regitf >= cdp_itfs + MAX_REG_ITFS || if (itfreg < cdp_itfs || itfreg >= cdp_itfs + MAX_REG_ITFS ||
!regitf->kind || !regitf->itfvtbl) !itfreg->name || !itfreg->itfvtbl)
{ {
fprintf (stderr, "cdp_Host_UnregisterItf(): " fprintf (stderr, "cdp_Host_UnregisterItf(): "
"Invalid or expired interface passed\n"); "Invalid or expired interface passed\n");
return; return;
} }
regitf->kind = CDPITF_KIND_INVALID; if (!itfreg->builtin)
regitf->itfvtbl = NULL; {
HFree ((void*) itfreg->name);
}
itfreg->module = NULL;
itfreg->name = NULL;
itfreg->itfvtbl = NULL;
}
static bool
cdp_Host_RegisterItfs (cdp_ItfDef* defs, cdp_Module* owner)
{
cdp_ItfDef* def;
int errors = 0;
for (def = defs; def->name; ++def)
{
def->reg = cdp_Host_RegisterItf (def->name, def->ver_from,
def->ver_to, def->itf, owner);
if (def->reg)
{
def->module = owner;
}
else
{
def->module = NULL;
++errors;
}
}
return !errors;
}
static void
cdp_Host_UnregisterItfs (cdp_ItfDef* defs)
{
cdp_ItfDef* def;
for (def = defs; def->name; ++def)
{
if (def->reg)
cdp_Host_UnregisterItf (def->reg);
}
}
/***********************************************************
* Event system *
***********************************************************/
cdp_EventReg*
cdp_GetEventReg (const char* name)
{
cdp_EventReg* evt;
for (evt = cdp_evts; evt->used &&
(!evt->name || stricmp(evt->name, name) != 0);
evt++)
;
if (!evt->name)
{
cdp_api_error = CDPERR_NO_EVENT;
return NULL;
}
return evt;
}
// hopefully inlinable
static cdp_Event
cdp_EventFromReg (cdp_EventReg* reg)
{
return (reg - cdp_evts) / sizeof (cdp_EventReg);
}
// hopefully inlinable
static cdp_EventReg*
cdp_RegFromEvent (cdp_Event event)
{
return cdp_evts + event;
}
cdp_Event
cdp_GetEvent (const char* name)
{
cdp_EventReg* reg;
reg = cdp_GetEventReg (name);
return reg ? cdp_EventFromReg (reg) : CDP_EVENT_INVALID;
}
static cdp_EventBind*
cdp_AllocEventBinds (cdp_EventBind* binds, uint32 ccur, uint32 cnew)
{
cdp_EventBind* newbinds;
uint32 newsize;
newsize = cnew * sizeof (cdp_EventBind);
if (binds)
newbinds = HRealloc (binds, newsize);
else
newbinds = HMalloc (newsize);
if (cnew > ccur)
memset (newbinds + ccur, 0,
(cnew - ccur) * sizeof (cdp_EventBind));
return newbinds;
}
static cdp_Event
cdp_Host_GetEvent (const char* name)
{
return cdp_GetEvent (name);
}
static bool
cdp_Host_GetEvents (cdp_EventDef* defs)
{
cdp_EventDef* def;
cdp_EventReg* reg;
int errors = 0;
for (def = defs; def->name; ++def)
{
// registration handle is not returned
def->reg = NULL;
reg = cdp_GetEventReg (def->name);
if (reg)
{
def->event = cdp_EventFromReg(reg);
def->name = reg->name; // set to cannonical name
def->module = reg->module;
}
else
{
def->event = CDP_EVENT_INVALID;
def->module = NULL;
++errors;
}
}
return !errors;
}
static cdp_EventReg*
cdp_Host_RegisterEvent (const char* name, cdp_Module* owner)
{
cdp_EventReg* evtreg;
cdp_EventReg* newslot = NULL;
char* id_name;
const char* ctx;
if (!owner)
{
fprintf (stderr, "cdp_Host_RegisterEvent(): "
"No owner info supplied\n");
//return NULL;
}
if (!name || !*name)
{
fprintf (stderr, "cdp_Host_RegisterEvent(): "
"Null or invalid event (from %s)\n",
cdp_GetModuleName (owner, true));
return NULL;
}
ctx = cdp_GetModuleContext (owner, false);
if (!ctx)
{
fprintf (stderr, "cdp_Host_RegisterEvent(): "
"Null or invalid context (from %s)\n",
cdp_GetModuleName (owner, true));
return NULL;
}
id_name = cdp_MakeContextName (ctx, name);
// check if event already registered
for (evtreg = cdp_evts; evtreg->used &&
(!evtreg->name || stricmp(evtreg->name, id_name) != 0);
++evtreg)
{
// and pick up an empty slot (where available)
if (!newslot && !evtreg->name)
newslot = evtreg;
}
if (evtreg >= cdp_evts + MAX_REG_EVENTS)
{
fprintf (stderr, "cdp_Host_RegisterEvent(): "
"Event limit reached\n");
HFree (id_name);
return NULL;
}
else if (evtreg->name)
{
fprintf (stderr, "cdp_Host_RegisterEvent(): "
"Event %s already registered, "
"%s denied\n",
name, cdp_GetModuleName (owner, true));
HFree (id_name);
return NULL;
}
if (!newslot)
{
newslot = evtreg;
newslot->used = true;
// make next one a term
evtreg[1].builtin = false;
evtreg[1].used = false;
evtreg[1].name = NULL;
}
newslot->name = id_name;
newslot->module = owner;
newslot->binds = NULL;
newslot->bindslots = 0;
return newslot;
}
static void
cdp_Host_UnregisterEvent (cdp_EventReg* evtreg)
{
if (evtreg < cdp_evts || evtreg >= cdp_evts + MAX_REG_EVENTS ||
!evtreg->name)
{
fprintf (stderr, "cdp_Host_UnregisterEvent(): "
"Invalid or expired event passed\n");
return;
}
if (!evtreg->builtin)
{
HFree ((void*) evtreg->name);
}
evtreg->module = NULL;
evtreg->name = NULL;
if (evtreg->binds)
HFree (evtreg->binds);
evtreg->binds = NULL;
evtreg->bindslots = 0;
}
static bool
cdp_Host_RegisterEvents (cdp_EventDef* defs, cdp_Module* owner)
{
cdp_EventDef* def;
int errors = 0;
for (def = defs; def->name; ++def)
{
def->reg = cdp_Host_RegisterEvent (def->name, owner);
if (def->reg)
{
def->module = owner;
}
else
{
def->module = NULL;
++errors;
}
}
return !errors;
}
static void
cdp_Host_UnregisterEvents (cdp_EventDef* defs)
{
cdp_EventDef* def;
for (def = defs; def->name; ++def)
{
if (def->reg)
cdp_Host_UnregisterEvent (def->reg);
}
}
static bool
cdp_Host_SubscribeEvent (cdp_Event event, cdp_EventProc proc, cdp_Module* module)
{
cdp_EventReg* reg = cdp_RegFromEvent (event);
cdp_EventBind* bind = NULL;
uint32 i;
if (reg < cdp_evts || reg >= cdp_evts + MAX_REG_EVENTS ||
!reg->name)
{
fprintf (stderr, "cdp_Host_SubscribeEvent(): "
"Invalid or expired event passed\n");
return false;
}
if (reg->binds)
{
// check for duplicate or find a new slot
for (i = 0, bind = reg->binds; i < reg->bindslots &&
(!bind->proc || bind->proc != proc);
++i, ++bind)
;
if (i >= reg->bindslots)
{ // full - add more slots
reg->binds = cdp_AllocEventBinds (reg->binds,
reg->bindslots, reg->bindslots + EVENT_BIND_GROW);
bind = reg->binds + reg->bindslots;
reg->bindslots += EVENT_BIND_GROW;
}
else if (bind->proc == proc)
{ // already bound
return true;
}
}
else
{
reg->binds = cdp_AllocEventBinds (NULL, 0, EVENT_BIND_GROW);
reg->bindslots = EVENT_BIND_GROW;
bind = reg->binds;
}
bind->proc = proc;
bind->module = module;
return true;
}
static void
cdp_Host_UnsubscribeEvent (cdp_Event event, cdp_EventProc proc)
{
cdp_EventReg* reg = cdp_RegFromEvent (event);
cdp_EventBind* bind = NULL;
uint32 i;
if (reg < cdp_evts || reg >= cdp_evts + MAX_REG_EVENTS ||
!reg->name)
{ // event either expired or invalid
return;
}
if (!reg->binds || !reg->bindslots)
return; // hmm, no bindings
// check for duplicate or find a new slot
for (i = 0, bind = reg->binds; i < reg->bindslots &&
bind->proc != proc;
++i, ++bind)
;
if (i >= reg->bindslots)
return; // binding not found
bind->proc = NULL;
bind->module = NULL;
}
static bool
cdp_Host_SubscribeEvents (cdp_EventDef* defs, cdp_Module* module)
{
cdp_EventDef* def;
int errors = 0;
for (def = defs; def->name; ++def)
{
if (def->event != CDP_EVENT_INVALID && def->proc)
if (!cdp_Host_SubscribeEvent (def->event, def->proc, module))
++errors;
}
return !errors;
}
static void
cdp_Host_UnsubscribeEvents (cdp_EventDef* defs)
{
cdp_EventDef* def;
for (def = defs; def->name; ++def)
{
if (def->event != CDP_EVENT_INVALID && def->proc)
cdp_Host_UnsubscribeEvent (def->event, def->proc);
}
}
static cdp_EventResult
cdp_Host_FireEvent (cdp_EventReg* evtreg, uint32 iparam, void* pparam)
{
bool bHandled = false;
cdp_EventResult ret = 0;
cdp_Event event;
cdp_EventBind* bind;
uint32 i;
if (evtreg < cdp_evts || evtreg >= cdp_evts + MAX_REG_EVENTS ||
!evtreg->name)
{
#ifdef DEBUG
fprintf (stderr, "cdp_Host_FireEvent(): Invalid event\n");
#endif
return 0;
}
if (!evtreg->binds)
return 0; // no subscribers
event = cdp_EventFromReg (evtreg);
// call event procs in opposite order of binding
for (i = evtreg->bindslots, bind = evtreg->binds + i - 1;
!bHandled && i > 0;
--i, --bind)
{
if (bind->proc)
ret = bind->proc (event, iparam, pparam, &bHandled);
}
return ret;
} }
+77 -23
View File
@@ -46,36 +46,76 @@ typedef enum
CDPERR_INIT_FAILED = 7, CDPERR_INIT_FAILED = 7,
CDPERR_NO_ITF = 8, CDPERR_NO_ITF = 8,
CDPERR_DUPE_ITF = 9, CDPERR_DUPE_ITF = 9,
CDPERR_NO_EVENT = 10,
CDPERR_DUPE_EVENT = 11,
CDPERR_OTHER = 1000, CDPERR_OTHER = 1000,
} cdp_Error; } cdp_Error;
typedef struct cdp_Module cdp_Module; typedef struct cdp_Module cdp_Module;
typedef void cdp_Itf; typedef void cdp_Itf;
typedef struct cdp_RegItf cdp_RegItf; typedef struct cdp_ItfReg cdp_ItfReg;
typedef enum // Interface KINDs - for convinience and uniformity
#define CDPITF_KIND_INVALID NULL
#define CDPITF_KIND_HOST "UQM.Host"
#define CDPITF_KIND_MEMORY "UQM.Memory"
#define CDPITF_KIND_IO "UQM.IO"
#define CDPITF_KIND_THREADS "UQM.Threads"
#define CDPITF_KIND_TIME "UQM.Time"
#define CDPITF_KIND_INPUT "UQM.Input"
#define CDPITF_KIND_TASK "UQM.Task"
#define CDPITF_KIND_RESOURCE "UQM.Resource"
#define CDPITF_KIND_SOUND "UQM.Sound"
#define CDPITF_KIND_VIDEO "UQM.Video"
#define CDPITF_KIND_GFX "UQM.Gfx"
#define CDPITF_KIND_MIXER "UQM.Mixer"
// Interface definition structure
// pass an array of these to Host->GetItfs() for batch lookup
// pass an array of these to Host->RegisterItfs() for batch registration
typedef struct
{ {
CDPITF_KIND_INVALID = 0, // fill in the first 4 members for batch registration
CDPITF_KIND_HOST = 1, // fill in the 1st member for batch lookup
CDPITF_KIND_MEMORY = 2, // terminate an array of these defs with name == NULL
CDPITF_KIND_IO = 3, const char* name; // interface ID
CDPITF_KIND_THREADS = 4, cdp_Itf* itf; // interface pointer
CDPITF_KIND_TIME = 5, cdp_ApiVersion ver_from; // lowest supported version
CDPITF_KIND_INPUT = 6, cdp_ApiVersion ver_to; // highest supported version
CDPITF_KIND_TASK = 7,
CDPITF_KIND_RESOURCE = 8,
CDPITF_KIND_SOUND = 9,
CDPITF_KIND_VIDEO = 10,
CDPITF_KIND_GFX = 11,
CDPITF_KIND_MIXER = 12,
// anything up to 65536 is reserved
// apply for your KIND (range) officially in UQM bugzilla (for now)
// custom interfaces live here cdp_Module* module; // owner module
# include "cdpitfs.h" // the following member is only set during registration
cdp_ItfReg* reg; // registration handle (not set on lookup)
} cdp_ItfKind; } cdp_ItfDef;
typedef unsigned int cdp_Event;
typedef struct cdp_EventReg cdp_EventReg;
typedef intptr_t cdp_EventResult;
#define CDP_EVENT_INVALID (-1)
// used with cdp_Event
typedef cdp_EventResult (* cdp_EventProc)
(cdp_Event, uint32, void*, bool* pbHandled);
// Event definition structure
// pass an array of these to Host->GetItfs() for batch lookup
typedef struct
{
// fill in the 1st member for batch lookup or registration
// also fill in the 2nd member for batch subscription
// terminate an array of these defs with name == NULL
const char* name; // event ID
cdp_EventProc proc; // event proc, set to NULL for no bind
cdp_Event event; // subscribable event handle
cdp_Module* module; // owner module
// the following member is only set during registration
cdp_EventReg* reg; // registration handle (not set on lookup)
} cdp_EventDef;
// Host Interface // Host Interface
// the main itf of the API, it is passed to a loaded module // the main itf of the API, it is passed to a loaded module
@@ -86,11 +126,25 @@ typedef struct
uint32 (* GetApiVersion) (void); uint32 (* GetApiVersion) (void);
uint32 (* GetVersion) (void); uint32 (* GetVersion) (void);
cdp_Error (* GetApiError) (void); cdp_Error (* GetApiError) (void);
cdp_Itf* (* GetItf) (cdp_ItfKind); cdp_Itf* (* GetItf) (const char* name);
cdp_RegItf* (* RegisterItf) (cdp_ItfKind, bool (* GetItfs) (cdp_ItfDef* defs);
cdp_ItfReg* (* RegisterItf) (const char* name,
cdp_ApiVersion ver_from, cdp_ApiVersion ver_to, cdp_ApiVersion ver_from, cdp_ApiVersion ver_to,
cdp_Itf*, cdp_Module*); cdp_Itf*, cdp_Module*);
void (* UnregisterItf) (cdp_RegItf*); void (* UnregisterItf) (cdp_ItfReg*);
bool (* RegisterItfs) (cdp_ItfDef* defs, cdp_Module*);
void (* UnregisterItfs) (cdp_ItfDef* defs);
cdp_Event (* GetEvent) (const char* name);
bool (* GetEvents) (cdp_EventDef* defs);
cdp_EventReg* (* RegisterEvent) (const char* name, cdp_Module*);
void (* UnregisterEvent) (cdp_EventReg*);
bool (* RegisterEvents) (cdp_EventDef* defs, cdp_Module*);
void (* UnregisterEvents) (cdp_EventDef* defs);
bool (* SubscribeEvent) (cdp_Event, cdp_EventProc, cdp_Module*);
void (* UnsubscribeEvent) (cdp_Event, cdp_EventProc);
bool (* SubscribeEvents) (cdp_EventDef* defs, cdp_Module*);
void (* UnsubscribeEvents) (cdp_EventDef* defs);
cdp_EventResult (* FireEvent) (cdp_EventReg*, uint32, void*);
} cdp_Itf_HostVtbl_v1; } cdp_Itf_HostVtbl_v1;
+2 -1
View File
@@ -42,6 +42,7 @@ extern cdp_Itf_SoundVtbl_v1 cdp_sound_itf_v1;
bool cdp_InitApi (void); bool cdp_InitApi (void);
void cdp_UninitApi (void); void cdp_UninitApi (void);
cdp_Error cdp_GetApiError (void); cdp_Error cdp_GetApiError (void);
cdp_Itf* cdp_GetInterface (cdp_ItfKind itf_kind, cdp_ApiVersion api_ver); cdp_Itf* cdp_GetInterface (const char* name, cdp_ApiVersion);
cdp_ItfReg* cdp_GetInterfaceReg (const char* name, cdp_ApiVersion);
#endif /* _CDPISND_H */ #endif /* _CDPISND_H */
+25 -12
View File
@@ -41,27 +41,40 @@ typedef struct
uint16 host_ver_major; // minimum host version required, purely informational uint16 host_ver_major; // minimum host version required, purely informational
uint16 host_ver_minor; uint16 host_ver_minor;
uint32 _32_reserved1[4]; // reserved members: set to all 0s or CDP_MODINFO_RESERVED1 // reserved members: set all to 0 or use CDP_MODINFO_RESERVED1
uint32 _32_reserved1;
uint32 _32_reserved2;
uint32 _32_reserved3;
uint32 _32_reserved4;
// informational, human-only const char* context_name;
const char* name; // cannonical context name (in proper case)
const char* ver_string; // this context will be used with all exposed objects
const char* author; // English preferred; try to keep it below 32 chars
const char* url; // informational, human-only; these fields have no real size
const char* comments; // restriction other than to keep it reasonable
const char* name; // descriptive name
const char* ver_string; // descriptive version
const char* author; // go nuts
const char* url; // go nuts
const char* comments; // go nuts
const char* _sz_reserved2[5]; // reserved members, set to all 0s or CDP_MODINFO_RESERVED2 // reserved members, set all to 0 or use CDP_MODINFO_RESERVED2
const char* _sz_reserved1;
const char* _sz_reserved2;
const char* _sz_reserved3;
const char* _sz_reserved4;
// mandatory, CDP entry points // mandatory, CDP entry points
// TODO: decide whether more EPs are necessary and if not move // TODO: decide whether more EPs are necessary and if not move
// EPs above info-string members, abolishing _sz_reserved2 // EPs above info-string members, abolishing _sz_reservedX
bool (* module_init) (cdp_Itf_Host* hostitf); bool (* module_init) (cdp_Module* module, cdp_Itf_Host* hostitf);
void (* module_term) (); void (* module_term) ();
} cdp_ModuleInfo; } cdp_ModuleInfo;
#define CDP_MODINFO_RESERVED1 {0,0,0,0} #define CDP_MODINFO_RESERVED1 0,0,0,0
#define CDP_MODINFO_RESERVED2 {0,0,0,0,0} #define CDP_MODINFO_RESERVED2 0,0,0,0
// the following is defined via the last mandatory member // the following is defined via the last mandatory member
#define CDP_MODINFO_MIN_SIZE \ #define CDP_MODINFO_MIN_SIZE \
+5 -1
View File
@@ -36,7 +36,11 @@ dlopen (const char *filename, int flag)
{ {
HMODULE hlib; HMODULE hlib;
hlib = LoadLibraryA (filename); if (filename == NULL)
hlib = GetModuleHandleA(NULL);
else
hlib = LoadLibraryA (filename);
if (!hlib) if (!hlib)
wdl_last_error = GetLastError (); wdl_last_error = GetLastError ();