Autoconf, Automake, and Libtool: Loading a Module

| ### 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