Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/docs/testing-rust-code/   (Beweissystem der NASA Version 6.0.9©) image not shown  

Quellcode-Bibliothek modules.c   Sprache: C

 
/****************************************************************************
**
**  This file is part of GAP, a system for computational discrete algebra.
**
**  Copyright of GAP belongs to its developers, whose names are too numerous
**  to list here. Please refer to the COPYRIGHT file for details.
**
**  SPDX-License-Identifier: GPL-2.0-or-later
**
**  This file implements APIs for GAP modules, including builtin modules,
**  or static and dynamic modules used by packages and end users to provide
**  kernel extensions.
*/


#include "modules.h"

#include "ariths.h"
#include "bool.h"
#include "code.h"
#include "compstat.h"
#include "error.h"
#include "funcs.h"
#include "gap.h"
#include "gapstate.h"
#include "gvars.h"
#include "integer.h"
#include "intobj.h"
#include "io.h"
#include "lists.h"
#include "modules_builtin.h"
#include "opers.h"
#include "plist.h"
#include "saveload.h"
#include "streams.h"
#include "stringobj.h"
#include "sysfiles.h"
#include "sysopt.h"
#include "sysstr.h"
#include "vars.h"

#include "config.h"

#ifdef HAVE_DLOPEN
#include <dlfcn.h>
#endif

#include <stdio.h>      // for fprintf, stderr


/****************************************************************************
**
*F  Modules . . . . . . . . . . . . . . . . . . . . . . . . . list of modules
*/

#ifndef MAX_MODULES
#define MAX_MODULES 1000
#endif


#ifndef MAX_MODULE_FILENAMES
#define MAX_MODULE_FILENAMES (MAX_MODULES * 50)
#endif

static Char   LoadedModuleFilenames[MAX_MODULE_FILENAMES];
static Char * NextLoadedModuleFilename = LoadedModuleFilenames;

typedef struct {

    // pointer to the actual StructInitInfo
    StructInitInfo * info;

    // filename relative to GAP_ROOT or absolute
    Char * filename;

    // true if the filename is GAP_ROOT relative
    Int isGapRootRelative;

} StructInitInfoExt;


static StructInitInfoExt Modules[MAX_MODULES];
static UInt       NrModules;
static UInt       NrBuiltinModules;


typedef struct {
    const Char * name;
    Obj *        address;
} StructImportedGVars;

#ifndef MAX_IMPORTED_GVARS
#define MAX_IMPORTED_GVARS 1024
#endif

static StructImportedGVars ImportedGVars[MAX_IMPORTED_GVARS];
static Int                 NrImportedGVars;

static StructImportedGVars ImportedFuncs[MAX_IMPORTED_GVARS];
static Int                 NrImportedFuncs;

static Int StateNextFreeOffset = 0; // Start of next free memory area (as offset into GAPState.StateSlots)

static void RegisterModuleState(StructInitInfo * info)
{
    UInt size = info->moduleStateSize;
    if (size == 0)
        return;

    if (SyDebugLoading) {
        fprintf(stderr, "#I module '%s' reserved %d bytes module state\n", info->name, (int)size);
    }

    // using moduleStateSize without moduleStateOffsetPtr makes no sense
    GAP_ASSERT(info->moduleStateOffsetPtr);

    // check that we have enough free space
    assert((STATE_SLOTS_SIZE - StateNextFreeOffset) >= size);

    // record start offset of this module's state
    *info->moduleStateOffsetPtr = StateNextFreeOffset;

    // ... and 'allocate' the requested amount of storage
    StateNextFreeOffset += size;
    StateNextFreeOffset = (StateNextFreeOffset + sizeof(Obj)-1) & ~(sizeof(Obj)-1);
}


/*************************************************************************
**
*F * * * * * * * * * functions for dynamical/static modules * * * * * * * * *
*/



/****************************************************************************
**
*F  FuncGAP_CRC( <self>, <name> ) . . . . . . . create a crc value for a file
*/

static Obj FuncGAP_CRC(Obj self, Obj filename)
{
    RequireStringRep(SELF_NAME, filename);
    return ObjInt_Int(SyGAPCRC(CONST_CSTR_STRING(filename)));
}


/****************************************************************************
**
*F  ActivateModule( <info> )
*/

Int ActivateModule(StructInitInfo * info)
{
    Int res = 0;

    RegisterModuleState(info);

    if (info->initKernel) {
        res = info->initKernel(info);
    }

    int flag = 0;
#ifdef GAP_ENABLE_SAVELOAD
    flag = SyRestoring != 0;
#endif
    if (!flag) {
        UpdateCopyFopyInfo();

        if (info->initLibrary) {
            // Start a new executor to run the outer function of the module in
            // global context
            Bag oldLvars = SWITCH_TO_BOTTOM_LVARS();
            res = res || info->initLibrary(info);
            SWITCH_TO_OLD_LVARS(oldLvars);
        }
    }

    if (res) {
        Pr("#W init functions returned non-zero exit code\n", 0, 0);
    }

    if (info->initModuleState)
        res = res || (info->initModuleState)();

    return res;
}


/****************************************************************************
**
*F  LookupStaticModule(<name>)
*/

StructInitInfo * LookupStaticModule(const char * name)
{
    for (int k = 0; CompInitFuncs[k]; k++) {
        StructInitInfo * info = (*(CompInitFuncs[k]))();
        if (info && streq(name, info->name)) {
            return info;
        }
    }
    return 0;
}


/****************************************************************************
**
*F  SyLoadModule( <name>, <func> )  . . . . . . . . .  load a compiled module
**
**  This function attempts to load a compiled module <name>.
**  If successful, it returns 0, and sets <func> to a pointer to the init
**  function of the module. In case of an error, <func> is set to 0, and the
**  return value is a pointer to a string with more information.
*/

#ifdef HAVE_DLOPEN
static const char * SyLoadModule(const Char * name, InitInfoFunc * func)
{
    void * handle = dlopen(name, RTLD_LAZY | RTLD_LOCAL);
    if (handle == 0) {
        *func = 0;
        return dlerror();
    }

    *func = (InitInfoFunc)dlsym(handle, "Init__Dynamic");
    if (*func == 0)
        return "symbol 'Init__Dynamic' not found";

    return 0;
}
#endif


/****************************************************************************
**
*F  FuncIS_LOADABLE_DYN( <self>, <name> ) . test if a dyn. module is loadable
*/

static Obj FuncIS_LOADABLE_DYN(Obj self, Obj filename)
{
    RequireStringRep(SELF_NAME, filename);

#if !defined(HAVE_DLOPEN)
    return False;
#else

    InitInfoFunc init;

    // try to load the module
    SyLoadModule(CONST_CSTR_STRING(filename), &init);
    if (init == 0)
        return False;

    // get the description structure
    StructInitInfo * info = (*init)();
    if (info == 0)
        return False;

    // info->type should not be larger than kernel version
    if (info->type / 10 > GAP_KERNEL_API_VERSION)
        return False;

    // info->type should not have an older major version
    if (info->type / 10000 < GAP_KERNEL_MAJOR_VERSION)
        return False;

    // info->type % 10 should be 0, 1 or 2, for the 3 types of module
    if (info->type % 10 > 2)
        return False;

    return True;
#endif
}


/****************************************************************************
**
*F  FuncLOAD_DYN( <self>, <name> ) . . . . . . . try to load a dynamic module
*/

static Obj FuncLOAD_DYN(Obj self, Obj filename)
{
    RequireStringRep(SELF_NAME, filename);

#if !defined(HAVE_DLOPEN)
    // no dynamic library support
    if (SyDebugLoading) {
        Pr("#I LOAD_DYN: no support for dynamical loading\n", 0, 0);
    }
    return False;
#else

    InitInfoFunc init;

    // try to read the module
    const char * res = SyLoadModule(CONST_CSTR_STRING(filename), &init);
    if (res)
        ErrorQuit("LOAD_DYN: failed to load kernel module %g, %s",
                  (Int)filename, (Int)res);

    // get the description structure
    StructInitInfo * info = (*init)();
    if (info == 0)
        ErrorQuit("LOAD_DYN: init function of kernel module %g failed",
                  (Int)filename, 0);

    // info->type should not be larger than kernel version
    if (info->type / 10 > GAP_KERNEL_API_VERSION)
        ErrorMayQuit("LOAD_DYN: kernel module %g built for newer "
                     "version %d of GAP",
                     (Int)filename, info->type / 10);

    // info->type should not have an older major version
    if (info->type / 10000 < GAP_KERNEL_MAJOR_VERSION)
        ErrorMayQuit("LOAD_DYN: kernel module %g built for older "
                     "version of GAP",
                     (Int)filename, 0);

    // info->type % 10 should be 0, 1 or 2, for the 3 types of module
    if (info->type % 10 > 2)
        ErrorMayQuit("LOAD_DYN: Invalid kernel module '%g'", (Int)filename,
                     0);

    ActivateModule(info);
    RecordLoadedModule(info, 0, CONST_CSTR_STRING(filename));

    return True;
#endif
}


/****************************************************************************
**
*F  FuncLOAD_STAT( <self>, <name> ) . . . . . . . try to load a static module
*/

static Obj FuncLOAD_STAT(Obj self, Obj filename)
{
    StructInitInfo * info = 0;

    RequireStringRep(SELF_NAME, filename);

    // try to find the module
    info = LookupStaticModule(CONST_CSTR_STRING(filename));
    if (info == 0) {
        if (SyDebugLoading) {
            Pr("#I LOAD_STAT: no module named '%g' found\n", (Int)filename,
               0);
        }
        return False;
    }

    ActivateModule(info);
    RecordLoadedModule(info, 0, CONST_CSTR_STRING(filename));

    return True;
}


/****************************************************************************
**
*F  FuncSHOW_STAT() . . . . . . . . . . . . . . . . . . . show static modules
*/

static Obj FuncSHOW_STAT(Obj self)
{
    Obj              modules;
    Obj              name;
    StructInitInfo * info;
    Int              k;
    Int              im;

    // count the number of install modules
    for (k = 0, im = 0; CompInitFuncs[k]; k++) {
        info = (*(CompInitFuncs[k]))();
        if (info == 0) {
            continue;
        }
        im++;
    }

    // make a list of modules with crc values
    modules = NEW_PLIST(T_PLIST, 2 * im);

    for (k = 0; CompInitFuncs[k]; k++) {
        info = (*(CompInitFuncs[k]))();
        if (info == 0) {
            continue;
        }
        name = MakeImmString(info->name);

        PushPlist(modules, name);

        // compute the crc value
        PushPlist(modules, ObjInt_Int(info->crc));
    }

    return modules;
}


/****************************************************************************
**
*F  FuncLoadedModules( <self> ) . . . . . . . . . . . list all loaded modules
*/

static Obj FuncLoadedModules(Obj self)
{
    Int              i;
    StructInitInfo * m;
    Obj              str;
    Obj              list;

    // create a list
    list = NEW_PLIST(T_PLIST, NrModules * 3);
    SET_LEN_PLIST(list, NrModules * 3);
    for (i = 0; i < NrModules; i++) {
        m = Modules[i].info;
        if (IS_MODULE_BUILTIN(m->type)) {
            SET_ELM_PLIST(list, 3 * i + 1, ObjsChar[(Int)'b']);
            CHANGED_BAG(list);
            str = MakeImmString(m->name);
            SET_ELM_PLIST(list, 3 * i + 2, str);
            SET_ELM_PLIST(list, 3 * i + 3, INTOBJ_INT(m->version));
        }
        else if (IS_MODULE_DYNAMIC(m->type)) {
            SET_ELM_PLIST(list, 3 * i + 1, ObjsChar[(Int)'d']);
            CHANGED_BAG(list);
            str = MakeImmString(m->name);
            SET_ELM_PLIST(list, 3 * i + 2, str);
            CHANGED_BAG(list);
            str = MakeImmString(Modules[i].filename);
            SET_ELM_PLIST(list, 3 * i + 3, str);
        }
        else if (IS_MODULE_STATIC(m->type)) {
            SET_ELM_PLIST(list, 3 * i + 1, ObjsChar[(Int)'s']);
            CHANGED_BAG(list);
            str = MakeImmString(m->name);
            SET_ELM_PLIST(list, 3 * i + 2, str);
            CHANGED_BAG(list);
            str = MakeImmString(Modules[i].filename);
            SET_ELM_PLIST(list, 3 * i + 3, str);
        }
    }
    return list;
}


/****************************************************************************
**
*F * * * * * * * * * * * * * initialize module * * * * * * * * * * * * * * *
*/



/****************************************************************************
**
*F  InitBagNamesFromTable( <table> )  . . . . . . . . .  initialise bag names
*/

void InitBagNamesFromTable(const StructBagNames * tab)
{
    Int i;

    for (i = 0; tab[i].tnum != -1; i++) {
        SET_TNAM_TNUM(tab[i].tnum, tab[i].name);
    }
}


/****************************************************************************
**
*F  InitClearFiltsTNumsFromTable( <tab> ) . . .  initialise clear filts tnums
*/

void InitClearFiltsTNumsFromTable(const Int * tab)
{
    Int i;

    for (i = 0; tab[i] != -1; i += 2) {
        ClearFiltsTNums[tab[i]] = tab[i + 1];
        ClearFiltsTNums[tab[i] | IMMUTABLE] = tab[i + 1] | IMMUTABLE;
    }
}


/****************************************************************************
**
*F  InitHasFiltListTNumsFromTable( <tab> )  . . initialise tester filts tnums
*/

void InitHasFiltListTNumsFromTable(const Int * tab)
{
    Int i;

    for (i = 0; tab[i] != -1; i += 3) {
        HasFiltListTNums[tab[i]][tab[i + 1]] = tab[i + 2];
        HasFiltListTNums[tab[i] | IMMUTABLE][tab[i + 1]] = tab[i + 2];
    }
}


/****************************************************************************
**
*F  InitSetFiltListTNumsFromTable( <tab> )  . . initialise setter filts tnums
*/

void InitSetFiltListTNumsFromTable(const Int * tab)
{
    Int i;

    for (i = 0; tab[i] != -1; i += 3) {
        SetFiltListTNums[tab[i]][tab[i + 1]] = tab[i + 2];
        SetFiltListTNums[tab[i] | IMMUTABLE][tab[i + 1]] =
            tab[i + 2] | IMMUTABLE;
    }
}


/****************************************************************************
**
*F  InitResetFiltListTNumsFromTable( <tab> )  initialise unsetter filts tnums
*/

void InitResetFiltListTNumsFromTable(const Int * tab)
{
    Int i;

    for (i = 0; tab[i] != -1; i += 3) {
        ResetFiltListTNums[tab[i]][tab[i + 1]] = tab[i + 2];
        ResetFiltListTNums[tab[i] | IMMUTABLE][tab[i + 1]] =
            tab[i + 2] | IMMUTABLE;
    }
}

static Obj ValidatedArgList(const char * name, int nargs, const char * argStr)
{
    Obj args = ArgStringToList(argStr);
    int len = LEN_PLIST(args);
    if (nargs >= 0 && len != nargs)
        fprintf(stderr,
                "#W %s takes %d arguments, but argument string is '%s'"
                " which implies %d arguments\n",
                name, nargs, argStr, len);
    return args;
}

/****************************************************************************
**
*F  InitGVarFiltsFromTable( <tab> ) . . . . . . . . . . . . . . . new filters
*/

void InitGVarFiltsFromTable(const StructGVarFilt * tab)
{
    Int i;

    for (i = 0; tab[i].name != 0; i++) {
        UInt gvar = GVarName(tab[i].name);
        Obj  name = NameGVar(gvar);
        Obj  args = ValidatedArgList(tab[i].name, 1, tab[i].argument);
        AssReadOnlyGVar(gvar, NewFilter(name, args, tab[i].handler));
    }
}


/****************************************************************************
**
*F  InitGVarAttrsFromTable( <tab> ) . . . . . . . . . . . . .  new attributes
*/

void InitGVarAttrsFromTable(const StructGVarAttr * tab)
{
    Int i;

    for (i = 0; tab[i].name != 0; i++) {
        UInt gvar = GVarName(tab[i].name);
        Obj  name = NameGVar(gvar);
        Obj  args = ValidatedArgList(tab[i].name, 1, tab[i].argument);
        AssReadOnlyGVar(gvar, NewAttribute(name, args, tab[i].handler));
    }
}

/****************************************************************************
**
*F  InitGVarPropsFromTable( <tab> ) . . . . . . . . . . . . .  new properties
*/

void InitGVarPropsFromTable(const StructGVarProp * tab)
{
    Int i;

    for (i = 0; tab[i].name != 0; i++) {
        UInt gvar = GVarName(tab[i].name);
        Obj  name = NameGVar(gvar);
        Obj  args = ValidatedArgList(tab[i].name, 1, tab[i].argument);
        AssReadOnlyGVar(gvar, NewProperty(name, args, tab[i].getter, tab[i].setter));
    }
}


/****************************************************************************
**
*F  InitGVarOpersFromTable( <tab> ) . . . . . . . . . . . . .  new operations
*/

void InitGVarOpersFromTable(const StructGVarOper * tab)
{
    Int i;

    for (i = 0; tab[i].name != 0; i++) {
        UInt gvar = GVarName(tab[i].name);
        Obj  name = NameGVar(gvar);
        Obj  args = ValidatedArgList(tab[i].name, tab[i].nargs, tab[i].args);
        AssReadOnlyGVar(
            gvar, NewOperation(name, tab[i].nargs, args, tab[i].handler));
    }
}

static void SetupFuncInfo(Obj func, const Char * cookie)
{
    // The string <cookie> usually has the form "PATH/TO/FILE.c:FUNCNAME".
    // We check if that is the case, and if so, split it into the parts before
    // and after the colon. In addition, the file path is cut to only contain
    // the last two '/'-separated components.
    const Char * pos = strchr(cookie, ':');
    if (pos) {
        Obj location = MakeImmString(pos + 1);

        Obj  filename;
        char buffer[512];
        Int  len = 511 < (pos - cookie) ? 511 : pos - cookie;
        memcpy(buffer, cookie, len);
        buffer[len] = 0;

        Char * start = strrchr(buffer, '/');
        if (start) {
            while (start > buffer && *(start - 1) != '/')
                start--;
        }
        else
            start = buffer;
        filename = MakeImmString(start);

        Obj body_bag = NewFunctionBody();
        SET_FILENAME_BODY(body_bag, filename);
        SET_LOCATION_BODY(body_bag, location);
        SET_BODY_FUNC(func, body_bag);
        CHANGED_BAG(body_bag);
        CHANGED_BAG(func);
    }
}

/****************************************************************************
**
*F  InitGVarFuncsFromTable( <tab> ) . . . . . . . . . . . . . . new functions
*/

void InitGVarFuncsFromTable(const StructGVarFunc * tab)
{
    Int i;

    for (i = 0; tab[i].name != 0; i++) {
        UInt gvar = GVarName(tab[i].name);
        Obj  name = NameGVar(gvar);
        Obj  args = ValidatedArgList(tab[i].name, tab[i].nargs, tab[i].args);
        Obj  func = NewFunction(name, tab[i].nargs, args, tab[i].handler);
        SetupFuncInfo(func, tab[i].cookie);
        AssReadOnlyGVar(gvar, func);
    }
}


/****************************************************************************
**
*F  InitHdlrFiltsFromTable( <tab> ) . . . . . . . . . . . . . . . new filters
*/

void InitHdlrFiltsFromTable(const StructGVarFilt * tab)
{
    Int i;

    for (i = 0; tab[i].name != 0; i++) {
        InitHandlerFunc(tab[i].handler, tab[i].cookie);
        InitFopyGVar(tab[i].name, tab[i].filter);
    }
}


/****************************************************************************
**
*F  InitHdlrAttrsFromTable( <tab> ) . . . . . . . . . . . . .  new attributes
*/

void InitHdlrAttrsFromTable(const StructGVarAttr * tab)
{
    Int i;

    for (i = 0; tab[i].name != 0; i++) {
        InitHandlerFunc(tab[i].handler, tab[i].cookie);
        InitFopyGVar(tab[i].name, tab[i].attribute);
    }
}


/****************************************************************************
**
*F  InitHdlrPropsFromTable( <tab> ) . . . . . . . . . . . . .  new properties
*/

void InitHdlrPropsFromTable(const StructGVarProp * tab)
{
    Int i;

    for (i = 0; tab[i].name != 0; i++) {
        InitHandlerFunc(tab[i].getter, tab[i].cookie1);
        InitHandlerFunc(tab[i].setter, tab[i].cookie2);
        InitFopyGVar(tab[i].name, tab[i].property);
    }
}


/****************************************************************************
**
*F  InitHdlrOpersFromTable( <tab> ) . . . . . . . . . . . . .  new operations
*/

void InitHdlrOpersFromTable(const StructGVarOper * tab)
{
    Int i;

    for (i = 0; tab[i].name != 0; i++) {
        InitHandlerFunc(tab[i].handler, tab[i].cookie);
        InitFopyGVar(tab[i].name, tab[i].operation);
    }
}


/****************************************************************************
**
*F  InitHdlrFuncsFromTable( <tab> ) . . . . . . . . . . . . . . new functions
*/

void InitHdlrFuncsFromTable(const StructGVarFunc * tab)
{
    Int i;

    for (i = 0; tab[i].name != 0; i++) {
        InitHandlerFunc(tab[i].handler, tab[i].cookie);
    }
}


/****************************************************************************
**
*F  ImportGVarFromLibrary( <name>, <address> )  . . .  import global variable
*/



void ImportGVarFromLibrary(const Char * name, Obj * address)
{
    if (NrImportedGVars == 1024) {
        Pr("#W warning: too many imported GVars\n", 0, 0);
    }
    else {
        ImportedGVars[NrImportedGVars].name = name;
        ImportedGVars[NrImportedGVars].address = address;
        NrImportedGVars++;
    }
    if (address != 0) {
        InitCopyGVar(name, address);
    }
}


/****************************************************************************
**
*F  ImportFuncFromLibrary( <name>, <address> )  . . .  import global function
*/



void ImportFuncFromLibrary(const Char * name, Obj * address)
{
    if (NrImportedFuncs == 1024) {
        Pr("#W warning: too many imported Funcs\n", 0, 0);
    }
    else {
        ImportedFuncs[NrImportedFuncs].name = name;
        ImportedFuncs[NrImportedFuncs].address = address;
        NrImportedFuncs++;
    }
    if (address != 0) {
        InitFopyGVar(name, address);
    }
}


/****************************************************************************
**
*F  FuncExportToKernelFinished( <self> )  . . . . . . . . . . check functions
*/

static Obj FuncExportToKernelFinished(Obj self)
{
    UInt i;
    Int  errs = 0;
    Obj  val;

    SyInitializing = 0;
    for (i = 0; i < NrImportedGVars; i++) {
        if (ImportedGVars[i].address == 0) {
            val = ValAutoGVar(GVarName(ImportedGVars[i].name));
            if (val == 0) {
                errs++;
                if (!SyQuiet) {
                    Pr("#W global variable '%s' has not been defined\n",
                       (Int)ImportedFuncs[i].name, 0);
                }
            }
        }
        else if (*ImportedGVars[i].address == 0) {
            errs++;
            if (!SyQuiet) {
                Pr("#W global variable '%s' has not been defined\n",
                   (Int)ImportedGVars[i].name, 0);
            }
        }
        else {
            MakeReadOnlyGVar(GVarName(ImportedGVars[i].name));
        }
    }

    for (i = 0; i < NrImportedFuncs; i++) {
        if (ImportedFuncs[i].address == 0) {
            val = ValAutoGVar(GVarName(ImportedFuncs[i].name));
            if (val == 0 || !IS_FUNC(val)) {
                errs++;
                if (!SyQuiet) {
                    Pr("#W global function '%s' has not been defined\n",
                       (Int)ImportedFuncs[i].name, 0);
                }
            }
        }
        else if (*ImportedFuncs[i].address == ErrorMustEvalToFuncFunc ||
                 *ImportedFuncs[i].address == ErrorMustHaveAssObjFunc) {
            errs++;
            if (!SyQuiet) {
                Pr("#W global function '%s' has not been defined\n",
                   (Int)ImportedFuncs[i].name, 0);
            }
        }
        else {
            MakeReadOnlyGVar(GVarName(ImportedFuncs[i].name));
        }
    }

    return errs == 0 ? True : False;
}


/****************************************************************************
**
*F  RecordLoadedModule( <module> )  . . . . . . . . store module in <Modules>
*/


void RecordLoadedModule(StructInitInfo * info,
                        Int              isGapRootRelative,
                        const Char *     filename)
{
    UInt len;
    if (NrModules == MAX_MODULES) {
        Panic("no room to record module");
    }
    len = strlen(filename);
    if (NextLoadedModuleFilename + len + 1 >
        LoadedModuleFilenames + MAX_MODULE_FILENAMES) {
        Panic("no room for module filename");
    }
    *NextLoadedModuleFilename = '\0';
    memcpy(NextLoadedModuleFilename, filename, len + 1);
    Modules[NrModules].info = info;
    Modules[NrModules].filename = NextLoadedModuleFilename;
    NextLoadedModuleFilename += len + 1;
    Modules[NrModules].isGapRootRelative = isGapRootRelative;
    NrModules++;
}

#ifdef GAP_ENABLE_SAVELOAD

void SaveModules(void)
{
    SaveUInt(NrModules - NrBuiltinModules);
    for (UInt i = NrBuiltinModules; i < NrModules; i++) {
        SaveUInt(Modules[i].info->type);
        SaveUInt(Modules[i].isGapRootRelative);
        SaveCStr(Modules[i].filename);
    }
}

void LoadModules(void)
{
    Char buf[256];
    UInt nMods = LoadUInt();
    for (UInt i = 0; i < nMods; i++) {
        UInt type = LoadUInt();
        UInt isGapRootRelative = LoadUInt();
        LoadCStr(buf, 256);
        if (isGapRootRelative)
            READ_GAP_ROOT(buf);
        else {
            StructInitInfo * info = NULL;
            // Search for user module static case first
            if (IS_MODULE_STATIC(type)) {
                info = LookupStaticModule(buf);
                if (info == 0) {
                    Panic("Static module %s not found in loading kernel",
                          buf);
                }
            }
            else {
                // and dynamic case
                InitInfoFunc init;

#ifdef HAVE_DLOPEN
                const char * res = SyLoadModule(buf, &init);
                if (init == 0) {
                    Panic("failed to load dynamic module %s, %s\n", buf, res);
                }
                info = (*init)();
                if (info == 0) {
                    Panic("failed to init dynamic module %s\n", buf);
                }
#else
                Panic("workspace require dynamic module %s, but dynamic "
                      "loading not supported",
                      buf);
#endif
            }

            ActivateModule(info);
            RecordLoadedModule(info, 0, buf);
        }
    }
}

#endif

void ModulesSetup(void)
{
    NrImportedGVars = 0;
    NrImportedFuncs = 0;
    NrModules = 0;
    for (UInt i = 0; InitFuncsBuiltinModules[i]; i++) {
        if (NrModules == MAX_MODULES) {
            Panic("too many builtin modules");
        }
        StructInitInfo * info = InitFuncsBuiltinModules[i]();
        Modules[NrModules++].info = info;
        if (SyDebugLoading) {
            fputs("#I InitInfo(builtin ", stderr);
            fputs(info->name, stderr);
            fputs(")\n", stderr);
        }

        RegisterModuleState(info);
    }
    NrBuiltinModules = NrModules;
}

void ModulesInitKernel(void)
{
    for (UInt i = 0; i < NrBuiltinModules; i++) {
        StructInitInfo * info = Modules[i].info;
        if (info->initKernel) {
            if (SyDebugLoading) {
                fputs("#I InitKernel(builtin ", stderr);
                fputs(info->name, stderr);
                fputs(")\n", stderr);
            }
            Int ret = info->initKernel(info);
            if (ret) {
                Panic("InitKernel(builtin %s) returned non-zero value", info->name);
            }
        }
    }
}

void ModulesInitLibrary(void)
{
    for (UInt i = 0; i < NrBuiltinModules; i++) {
        StructInitInfo * info = Modules[i].info;
        if (info->initLibrary) {
            if (SyDebugLoading) {
                fputs("#I InitLibrary(builtin ", stderr);
                fputs(info->name, stderr);
                fputs(")\n", stderr);
            }
            Int ret = info->initLibrary(info);
            if (ret) {
                Panic("InitLibrary(builtin %s) returned non-zero value", info->name);
            }
        }
    }
}

void ModulesCheckInit(void)
{
    for (UInt i = 0; i < NrModules; i++) {
        StructInitInfo * info = Modules[i].info;
        if (info->checkInit) {
            if (SyDebugLoading) {
                fputs("#I CheckInit(builtin ", stderr);
                fputs(info->name, stderr);
                fputs(")\n", stderr);
            }
            Int ret = info->checkInit(info);
            if (ret) {
                Panic("CheckInit(builtin %s) returned non-zero value", info->name);
            }
        }
    }
}

void ModulesInitModuleState(void)
{
    for (UInt i = 0; i < NrModules; i++) {
        StructInitInfo * info = Modules[i].info;
        if (info->initModuleState) {
            if (SyDebugLoading) {
                fputs("#I InitModuleState(", stderr);
                fputs(info->name, stderr);
                fputs(")\n", stderr);
            }
            Int ret = info->initModuleState();
            if (ret) {
                Panic("InitModuleState(builtin %s) returned non-zero value", info->name);
            }
        }
    }
}

void ModulesDestroyModuleState(void)
{
    for (UInt i = 0; i < NrModules; i++) {
        StructInitInfo * info = Modules[i].info;
        if (info->destroyModuleState) {
            if (SyDebugLoading) {
                fputs("#I DestroyModuleState(", stderr);
                fputs(info->name, stderr);
                fputs(")\n", stderr);
            }
            Int ret = info->destroyModuleState();
            if (ret) {
                Panic("DestroyModuleState(builtin %s) returned non-zero value", info->name);
            }
        }
    }
}


#ifdef GAP_ENABLE_SAVELOAD

Int ModulesPreSave(void)
{
    for (UInt i = 0; i < NrModules; i++) {
        StructInitInfo * info = Modules[i].info;
        if (info->preSave != NULL && info->preSave(info)) {
            Pr("Failed to save workspace -- problem reported in %s\n",
               (Int)info->name, 0);
            // roll back all save preparations
            while (i--) {
                info = Modules[i].info;
                info->postSave(info);
            }
            return 1;
        }
    }
    return 0;
}

void ModulesPostSave(void)
{
    for (UInt i = 0; i < NrModules; i++) {
        StructInitInfo * info = Modules[i].info;
        if (info->postSave != NULL)
            info->postSave(info);
    }
}

void ModulesPostRestore(void)
{
    for (UInt i = 0; i < NrModules; i++) {
        StructInitInfo * info = Modules[i].info;
        if (info->postRestore) {
            if (SyDebugLoading) {
                fputs("#I PostRestore(builtin ", stderr);
                fputs(info->name, stderr);
                fputs(")\n", stderr);
            }
            Int ret = info->postRestore(info);
            if (ret) {
                Panic("PostRestore(builtin %s) returned non-zero value", info->name);
            }
        }
    }
}

#endif


/****************************************************************************
**
*V  GVarFuncs . . . . . . . . . . . . . . . . . . list of functions to export
*/

static StructGVarFunc GVarFuncs[] = {
    GVAR_FUNC_1ARGS(GAP_CRC, filename),
    GVAR_FUNC_1ARGS(IS_LOADABLE_DYN, filename),
    GVAR_FUNC_1ARGS(LOAD_DYN, filename),
    GVAR_FUNC_1ARGS(LOAD_STAT, filename),
    GVAR_FUNC_0ARGS(SHOW_STAT),
    GVAR_FUNC_0ARGS(LoadedModules),
    GVAR_FUNC_0ARGS(ExportToKernelFinished),
    { 0, 0, 0, 0, 0 }
};


/****************************************************************************
**
*F  InitKernel( <module> )  . . . . . . . . initialise kernel data structures
*/

static Int InitKernel(StructInitInfo * module)
{
    // init filters and functions
    InitHdlrFuncsFromTable(GVarFuncs);

    return 0;
}


/****************************************************************************
**
*F  InitLibrary( <module> ) . . . . . . .  initialise library data structures
*/

static Int InitLibrary(StructInitInfo * module)
{
    // init filters and functions
    InitGVarFuncsFromTable(GVarFuncs);

    return 0;
}


/****************************************************************************
**
*F  InitInfoModules() . . . . . . . . . . . . . . . . table of init functions
*/

static StructInitInfo module = {
    // init struct using C99 designated initializers; for a full list of
    // fields, please refer to the definition of StructInitInfo
    .type = MODULE_BUILTIN,
    .name = "modules",
    .initKernel = InitKernel,
    .initLibrary = InitLibrary,
};

StructInitInfo * InitInfoModules(void)
{
    return &module;
}

92%


¤ Dauer der Verarbeitung: 0.27 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.