|
20.1.3 Loading a Module
Individual modules are managed by finding specified entry points
(prescribed exported symbols) in the module:
- Variable: const Builtin * builtin_table
- An array of names of built-in commands implemented by a module, with
associated handler functions.
- Function: void module_init (Sic *sic)
- If present, this function will be called when the module is loaded.
- Function: void module_finish (Sic *sic)
- If supplied, this function will be called just before the module is
unloaded.
- Variable: const Syntax * syntax_table
- An array of syntactically significant symbols, and associated handler
functions.
- Function: int syntax_init (Sic *sic)
- If specified, this function will be called by Sic before the syntax of
each input line is analysed.
- Function: int syntax_finish (Sic *sic, BufferIn *in, BufferOut *out)
- Similarly, this function will be call after the syntax analysis of each
line has completed.
All of the hard work in locating and loading the module, and extracting
addresses for the symbols described above is performed by
libltdl. The module_load function below simply registers
these symbols with the Sic interpreter so that they are called at the
appropriate times -- or diagnoses any errors if things don't go
according to plan:
|
int
module_load (Sic *sic, const char *name)
{
lt_dlhandle module;
Builtin *builtin_table;
Syntax *syntax_table;
int status = SIC_OKAY;
last_error = NULL;
module = lt_dlopenext (name);
if (module)
{
builtin_table = (Builtin*) lt_dlsym (module, "builtin_table");
syntax_table = (Syntax *) lt_dlsym (module, "syntax_table");
if (!builtin_table && !syntax_table)
{
lt_dlclose (module);
last_error = no_builtin_table_error;
module = NULL;
}
}
if (module)
{
ModuleInit *init_func
= (ModuleInit *) lt_dlsym (module, "module_init");
if (init_func)
(*init_func) (sic);
}
if (module)
{
SyntaxFinish *syntax_finish
= (SyntaxFinish *) lt_dlsym (module, "syntax_finish");
SyntaxInit *syntax_init
= (SyntaxInit *) lt_dlsym (module, "syntax_init");
if (syntax_finish)
sic->syntax_finish = list_cons (list_new (syntax_finish),
sic->syntax_finish);
if (syntax_init)
sic->syntax_init = list_cons (list_new (syntax_init),
sic->syntax_init);
}
if (module)
{
if (builtin_table)
status = builtin_install (sic, builtin_table);
if (syntax_table && status == SIC_OKAY)
status = syntax_install (sic, module, syntax_table);
return status;
}
last_error = lt_dlerror();
if (!last_error)
last_error = module_not_found_error;
return SIC_ERROR;
}
|
Notice that the generalised List data type introduced earlier
(see section 9. A Small GNU Autotools Project) is reused to keep a list of
accumulated module initialisation and finalisation functions.
|