Changes:
1) Renamed functions (better/clearer/more consistent names)
2) added *_stop (symmetry, and for unloading)
3) removed possiblity that name_interface (now name_supplies) be dynamic
(allows cleaner handling of loading modules)
4) added *_uses and *_use_functions
DevMUD intermodule protocol, version 0.2. Comment away!
Each module should have a short name, and export symbols with that as a
prefix. The unique names are to allow static linking as well as dynamic.
A module named "name" would export these symbols:
int name_initialize(void);
int name_start(void);
int name_stop(void);
struct function *name_supplies;
struct function *name_uses;
void name_use_functions(struct function *funcs);
There may be a need for some more symbols, but they're not
present in this version. Candidates include a version
number and a description string.
Exporting symbols without the prefix is discouraged, but not formally
considered a bug unless a conflict arises.
What they mean:
name_initialize:
This is the first function called after the module is loaded. It
should do any initial setup required before the module gets
configured. If it returns anything except zero, it indicates that the
module was not correctly configured, and should be ignored.
Until name_initialize has been called, name_interface is not required
to be valid, and calling name_start may do nonsensical things like
crash.
name_start:
Calling name_start tells the module that it has been correctly
configured, and that it should start performing its in-game duties.
For example, a main socket module should open the socket in
socket_start. A return value other than zero indicates that something
went wrong, and that the module may not be performing correctly.
Modules writers should keep in mind that name_start isn't called
simultaneously for all modules, so a module may be configured to
work with temporarily unresponsive modules.
name_stop:
Calling name_stop asks the module to stop processings if it can,
and prepare to be unloaded. A return value of zero indicates that
the module has ceased processing, and is safe to unload. Any other
return value indicates that the module is not able to shut down for
some reason.
It may be necessary to call name_stop more than once, since the module
may take time for existing processing to complete. A module may
return -1 to indicate that expects to never be unloadable.
name_supplies:
This is an array of function-describing structures.
The format should look something like:
struct function {
char *name; /* what the function is called */
void *function; /* a function pointer */
char *prototype; /* arguments to the function */
char *description; /* human-readable text */
}
Each (name,prototype) pair should be unique. Multiple functions
can have the same name in order to support some degree of
polymorphism. For example, a function taking text input might
have two entries, one taking a Unicode string and the other an
ASCII string.
The prototype should contain enough information to verify that the
function will be called correctly. I'm envisioning something like
"int (char*,char*)" as being the format string for a function taking
two character pointers and returning an integer. We should
eventually write a verifyer program to check that these declarations
are correct. Shorthands for various types (like "string" for "char*")
should be developed, especially when it adds useful information.
UTFstring might indicate a string required to be in UTF-8 format,
for example. A naive implementation may simply strcmp() prototypes
to verify that they match.
The description should be human readable if present, but may be
NULL to indicate that a description isn't available.
The array should be terminated with a {NULL,NULL,NULL,NULL} entry.
name_uses:
This is another array of struct function. It lists functions
that the module knows how to use. It is intended to aid the
Config module in configuring a viable MUD. The function element
of the structure should be NULL. Otherwise it is very similar to
the name_supplies structure.
name_use_functions:
This takes an array of struct function (like some other module's
name_supplies), and tells the called module to use the functions in
it. The loader provides some (as yet unspecified) utility functions
to aid in the configuration process.
All of this specification is to allow the Config module to do its job. The
only requirement for the Config module is that it not make bad assumptions
beyond what the protocol guarantees.
Jon Leonard