-
Notifications
You must be signed in to change notification settings - Fork 20
DynamicExtensionLibraries
libslax provides a means of dynamically loading extension libraries based on the contents of the "extension-element-prefixes" attribute. During initialization, a parsed SLAX document is inspected for both the "extension-element-prefix" attribute on the element, and the "xsl:extension-element-prefix" on arbitrary tags.
The prefixes found in the document are translated into namespace URIs, which are then escaped using the URL-escaping algorithm that turns unacceptable characters into three character strings like "%2F".
An extension of ".ext" is appended to the URL-escaped URI and this file is searched but in ${SLAX_EXTDIR} and any directories given via the "--lib/-L" argument.
When the extension library is found, we dlopen() it and look for the magic symbol "slaxDynLibInit". This function is called with two arguments, the API version number and a struct that contains information about the extension library.
/*
* This structure is an interface between the libslax main code
* and the code in the extension library. This structure should
* only be extended by additions to the end.
*/
typedef struct slax_dyn_arg_s {
unsigned da_version; /* Version of the caller */
void *da_handle; /* Handle from dlopen() */
void *da_custom; /* Memory hook for the extension */
char *da_uri; /* URI */
slax_function_table_t *da_functions; /* Table of functions */
slax_element_table_t *da_elements; /* Table of elements */
} slax_dyn_arg_t;
The da_functions and da_elements allow the library to register and unregister there functions and elements.
At cleanup time, in addition to removing functions and elements, a search is made for the library to find the symbol "slaxDynLibClean". If the symbol is found, it is called also.
The file slaxdyn.h defines some macros for helping define extension libraries.
Here's an example:
slax_function_table_t slaxBitTable[] = {
{ "and", extBitAnd },
{ "or", extBitOr },
{ "nand", extBitNand },
{ "nor", extBitNor },
{ "xor", extBitXor },
{ "xnor", extBitXnor },
{ "not", extBitNot },
{ NULL, NULL },
};
SLAX_DYN_FUNC(slaxDynLibInit)
{
arg->da_functions = slaxBitTable; /* Fill in our function table */
return SLAX_DYN_VERSION;
}
"slaxproc -v" will tell you the path names slaxproc uses to find the extension library:
extension: attempting /Users/phil/work/root/lib/slax/extensions/http%3A%2F%2Fexample.com%2Ffoo.ext
extension: attempting /tmp/http%3A%2F%2Fexample.com%2Ffoo.ext
extension: attempting /Users/phil/work/root/lib/slax/extensions/http%3A%2F%2Fexample.com%2Ffoo.ext
extension: attempting /Users/phil/work/root/lib/slax/extensions/http%3A%2F%2Fcode.google.com%2Fp%2Flibslax%2Fslax.ext
extension: attempting /tmp/http%3A%2F%2Fcode.google.com%2Fp%2Flibslax%2Fslax.ext
extension: attempting /Users/phil/work/root/lib/slax/extensions/http%3A%2F%2Fcode.google.com%2Fp%2Flibslax%2Fslax.ext
extension: attempting /Users/phil/work/root/lib/slax/extensions/http%3A%2F%2Fexample.com%2Fgoo.ext
extension: attempting /tmp/http%3A%2F%2Fexample.com%2Fgoo.ext
extension: attempting /Users/phil/work/root/lib/slax/extensions/http%3A%2F%2Fexample.com%2Fgoo.ext
extension: attempting /Users/phil/work/root/lib/slax/extensions/http%3A%2F%2Fexample.com%2Fzoo.ext
extension: attempting /tmp/http%3A%2F%2Fexample.com%2Fzoo.ext
extension: attempting /Users/phil/work/root/lib/slax/extensions/http%3A%2F%2Fexample.com%2Fzoo.ext
extension: attempting /Users/phil/work/root/lib/slax/extensions/http%3A%2F%2Fexample.com%2Fyoo.ext
extension: attempting /tmp/http%3A%2F%2Fexample.com%2Fyoo.ext
extension: attempting /Users/phil/work/root/lib/slax/extensions/http%3A%2F%2Fexample.com%2Fyoo.ext