Back: Managing Module Loader Errors
Forward: Unloading a Module
 
FastBack: Unloading a Module
Up: A Module Loading Subsystem
FastForward: A Loadable Module
Top: Autoconf, Automake, and Libtool
Contents: Table of Contents
Index: Index
About: About this document

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.



This document was generated by Gary V. Vaughan on February, 8 2006 using texi2html