### 76 GAP Packages

The functionality of GAP can be extended by loading GAP packages. GAP distribution already contains all currently redistributed with GAP packages in the gap4r6/pkg directory.

GAP packages are written by (groups of) GAP users which may not be members of the GAP developer team. The responsibility and copyright of a GAP package remains with the original author(s).

GAP packages have their own documentation which is smoothly integrated into the GAP help system.

All GAP users who develop new code are invited to share the results of their efforts with other GAP users by making the code and its documentation available in form of a package. Information how to do this is available from the GAP Web pages (http://www.gap-system.org) and in the GAP package Example (see http://www.gap-system.org/Packages/example.html). There are possibilities to get a package distributed together with GAP and it is possible to submit a package to a formal refereeing process.

In this chapter we describe how to use existing packages.

#### 76.1 Installing a GAP Package

Before a package can be used it must be installed. With a standard installation of GAP there should be all currently redistributed with GAP packages already available. But since GAP packages are released independently of the main GAP system it may be sensible to upgrade or install new packages between upgrades of your GAP installation.

A package consists of a collection of files within a single directory that must be a subdirectory of the pkg directory in one of the GAP root directories, see 9.2. (If you don't have access to the pkg directory in your main GAP installation you can add private root directories as explained in that section.)

Whenever you get from somewhere an archive of a GAP package it should be accompanied with a README file that explains its installation. Some packages just consist of GAP code and the installation is done by unpacking the archive in one of the places described above. There are also packages that need further installation steps, there may be for example some external programs which have to be compiled (this is often done by just saying ./configure; make inside the unpacked package directory, but check the individual README files). Note that if you use Windows you may not be able to use some or all external binaries.

Some GAP packages are prepared for automatic loading, that is they will be loaded automatically with GAP, others must in each case be separately loaded by a call to LoadPackage (76.2-1).

 ‣ LoadPackage( name[, version][, banner] ) ( function )

loads the GAP package with name name. If the optional version string version is given, the package will only be loaded in a version number at least as large as version, or equal to version if its first character is = (see CompareVersionNumbers (76.3-6)). The argument name is case insensitive.

LoadPackage will return true if the package has been successfully loaded and will return fail if the package could not be loaded. The latter may be the case if the package is not installed, if necessary binaries have not been compiled, or if the version number of the available version is too small. If the package cannot be loaded, TestPackageAvailability (76.3-2) can be used to find the reasons. Also, DisplayPackageLoadingLog (76.2-4) can be used to find out more about the failure reasons. To see the problems directly, one can change the verbosity using the user preference InfoPackageLoadingLevel, see InfoPackageLoading (76.2-4) for details.

If the package name has already been loaded in a version number at least or equal to version, respectively, LoadPackage returns true without doing anything else.

The argument name may be the prefix of a package name. If no package with name name is installed, the behaviour is as follows. If name is the prefix of exactly one name of an installed package then LoadPackage is called with this name; if the names of several installed packages start with name then the these names are printed, and LoadPackage returns fail. Thus the names of all installed packages can be shown by calling LoadPackage with an empty string.

If the optional argument banner is present then it must be either true or false; in the latter case, the effect is that no package banner is printed.

After a package has been loaded its code and documentation should be available as other parts of the GAP library are.

When GAP is started then some packages are loaded automatically. These are the packages listed in GAPInfo.Dependencies.NeededOtherPackages and (if this is not disabled, see below) UserPreference( "PackagesToLoad" ).

A GAP package may also install only its documentation automatically but still need loading by LoadPackage. In this situation the online help displays (not loaded) in the header lines of the manual pages belonging to this GAP package.

If for some reason you don't want certain packages to be automatically loaded, GAP provides three levels for disabling autoloading:

The autoloading of specific packages can be overwritten for the whole GAP installation by putting a file NOAUTO into a pkg directory that contains lines with the names of packages which should not be automatically loaded.

Furthermore, individual users can disable the autoloading of specific packages by putting the names of these packages into the list that is assigned to the user preference "ExcludeFromAutoload", for example in the user's gap.ini file (see 3.2-1).

Using the -A command line option when starting up GAP (see 3.1), automatic loading of packages is switched off for this GAP session.

In any of the above three cases, the packages listed in GAPInfo.Dependencies.NeededOtherPackages are still loaded automatically, and an error is signalled if not all of these packages are available.

See SetPackagePath (76.2-2) for a possibility to force that a prescribed package version will be loaded. See also ExtendRootDirectories (76.2-3) for a possibility to add directories containing packages after GAP has been started.

##### 76.2-2 SetPackagePath
 ‣ SetPackagePath( pkgname, pkgpath ) ( function )

Let pkgname and pkgpath be strings denoting the name of a GAP package and the path to a directory where a version of this package can be found (i. e., calling Directory (9.3-2) with the argument pkgpath will yield a directory that contains the file PackageInfo.g of the package).

If the package pkgname is already loaded with an installation path different from pkgpath then SetPackagePath signals an error. If the package pkgname is not yet loaded then SetPackagePath erases the information about available versions of the package pkgname, and stores the record that is contained in the PackageInfo.g file at pkgpath instead, such that only the version installed at pkgpath can be loaded with LoadPackage (76.2-1).

This function can be used to force GAP to load a particular version of a package, although newer versions of the package might be available.

##### 76.2-3 ExtendRootDirectories
 ‣ ExtendRootDirectories( paths ) ( function )

Let paths be a list of strings that denote paths to intended GAP root directories (see 9.2). The function ExtendRootDirectories adds these paths to the global list GAPInfo.RootPaths and calls the initialization of available GAP packages, such that later calls to LoadPackage (76.2-1) will find the GAP packages that are contained in pkg subdirectories of the directories given by paths.

Note that the purpose of this function is to make GAP packages in the given directories available. It cannot be used to influence the start of GAP, because the GAP library is loaded before ExtendRootDirectories can be called (and because GAPInfo.RootPaths is not used for reading the GAP library).

 ‣ DisplayPackageLoadingLog( [severity] ) ( function )
 ‣ InfoPackageLoading ( info class )
 ‣ PACKAGE_ERROR ( global variable )
 ‣ PACKAGE_WARNING ( global variable )
 ‣ PACKAGE_INFO ( global variable )
 ‣ PACKAGE_DEBUG ( global variable )
 ‣ LogPackageLoadingMessage( severity, message[, name] ) ( function )

Whenever GAP considers loading a package, log messages are collected in a global list. The messages for the current GAP session can be displayed with DisplayPackageLoadingLog. To each message, a "severity" is assigned, which is one of PACKAGE_ERROR, PACKAGE_WARNING, PACKAGE_INFO, PACKAGE_DEBUG, in increasing order. The function DisplayPackageLoadingLog shows only the messages whose severity is at most severity, the default for severity is PACKAGE_WARNING.

The intended meaning of the severity levels is as follows.

PACKAGE_ERROR

should be used whenever GAP will run into an error during package loading, where the reason of the error shall be documented in the global list.

PACKAGE_WARNING

should be used whenever GAP has detected a reason why a package cannot be loaded, and where the message describes how to solve this problem, for example if a package binary is missing.

PACKAGE_INFO

should be used whenever GAP has detected a reason why a package cannot be loaded, and where it is not clear how to solve this problem, for example if the package is not compatible with other installed packages.

PACKAGE_DEBUG

should be used for other messages reporting what GAP does when it loads packages (checking dependencies, reading files, etc.). One purpose is to record in which order packages have been considered for loading or have actually been loaded.

The log messages are created either by the functions of GAP's package loading mechanism or in the code of your package, for example in the AvailabilityTest function of the package's PackageInfo.g file (see 76.3-11), using LogPackageLoadingMessage. The arguments of this function are severity (which must be one of the above severity levels), message (which must be either a string or a list of strings), and optionally name (which must be the name of the package to which the message belongs). The argument name is not needed if the function is called from a call of a package's AvailabilityTest function (see 76.3-11) or is called from a package file that is read from init.g or read.g; in these cases, the name of the current package (stored in the record GAPInfo.PackageCurrent) is taken. According to the above list, the severity argument of LogPackageLoadingMessage calls in a package's AvailabilityTest function is either PACKAGE_WARNING or PACKAGE_INFO.

If you want to see the log messages already during the package loading process, you can set the level of the info class InfoPackageLoading to one of the severity values listed above; afterwards the messages with at most this severity are shown immediately when they arise. In order to make this work already for autoloaded packages, you can call SetUserPreference("InfoPackageLoadingLevel", lev); to set the desired severity level lev. This can for example be done in your gap.ini file, see Section 3.2-1.

#### 76.3 Functions for GAP Packages

The following functions are mainly used in files contained in a package and not by users of a package.

 ‣ ReadPackage( [name, ]file ) ( function )
 ‣ RereadPackage( [name, ]file ) ( function )

Called with two strings name and file, ReadPackage reads the file file of the GAP package name, where file is given as a path relative to the home directory of name. Note that file is read in the namespace of the package, see Section 4.10 for details.

If only one argument file is given, this should be the path of a file relative to the pkg subdirectory of GAP root paths (see 9.2). Note that in this case, the package name is assumed to be equal to the first part of file, so the one argument form is not recommended.

The absolute path is determined as follows. If the package in question has already been loaded then the file in the directory of the loaded version is read. If the package is available but not yet loaded then the directory given by TestPackageAvailability (76.3-2) is used, without prescribed version number. (Note that the ReadPackage call does not force the package to be loaded.)

If the file is readable then true is returned, otherwise false.

Each of name and file should be a string. The name argument is case insensitive.

RereadPackage does the same as ReadPackage, except that also read-only global variables are overwritten (cf. Reread (9.7-9)).

##### 76.3-2 TestPackageAvailability
 ‣ TestPackageAvailability( name[, version][, checkall] ) ( function )

For strings name and version, this function tests whether the GAP package name is available for loading in a version that is at least version, or equal to version if the first character of version is = (see CompareVersionNumbers (76.3-6) for further details about version numbers).

The result is true if the package is already loaded, fail if it is not available, and the string denoting the GAP root path where the package resides if it is available, but not yet loaded. So the package name is available if the result of TestPackageAvailability is not equal to fail.

If the optional argument checkall is true then all dependencies are checked, even if some have turned out to be not satisfied. This is useful when one is interested in the reasons why the package name cannot be loaded. In this situation, calling first TestPackageAvailability and then DisplayPackageLoadingLog (76.2-4) with argument PACKAGE_INFO (76.2-4) will give an overview of these reasons.

You should not call TestPackageAvailability in the test function of a package (the value of the component AvailabilityTest in the PackageInfo.g file of the package, see 76.3-11), because TestPackageAvailability calls this test function.

The argument name is case insensitive.

##### 76.3-3 InstalledPackageVersion
 ‣ InstalledPackageVersion( name ) ( function )

If the GAP package with name name has already been loaded then InstalledPackageVersion returns the string denoting the version number of this version of the package. If the package is available but has not yet been loaded then the version number string for that version of the package that currently would be loaded. (Note that loading another package might force loading another version of the package name, so the result of InstalledPackageVersion will be different afterwards.) If the package is not available then fail is returned.

The argument name is case insensitive.

##### 76.3-4 DirectoriesPackageLibrary
 ‣ DirectoriesPackageLibrary( name[, path] ) ( function )

takes the string name, a name of a GAP package, and returns a list of directory objects for those sub-directory/ies containing the library functions of this GAP package, for the version that is already loaded or is currently going to be loaded or would be the first version GAP would try to load if no other version is explicitly prescribed. (If the package name is not yet loaded then we cannot guarantee that the returned directories belong to a version that really can be loaded.)

The default is that the library functions are in the subdirectory lib of the GAP package's home directory. If this is not the case, then the second argument path needs to be present and must be a string that is a path name relative to the home directory of the GAP package with name name.

Note that DirectoriesPackageLibrary is likely to be called in the AvailabilityTest function in the package's PackageInfo.g file (see 76.3-11).

As an example, the following returns a directory object for the library functions of the GAP package Example:

gap> DirectoriesPackageLibrary( "Example", "gap" );
[ dir("/home/werner/gap/4.0/pkg/example/gap/") ]


Observe that we needed the second argument "gap" here, since Example's library functions are in the subdirectory gap rather than lib.

In order to find a subdirectory deeper than one level in a package directory, the second argument is again necessary whether or not the desired subdirectory relative to the package's directory begins with lib. The directories in path should be separated by / (even on systems, like Windows, which use \ as the directory separator). For example, suppose there is a package somepackage with a subdirectory m11 in the directory data, then we might expect the following:

gap> DirectoriesPackageLibrary( "somepackage", "data/m11" );
[ dir("/home/werner/gap/4.0/pkg/somepackage/data/m11") ]


##### 76.3-5 DirectoriesPackagePrograms
 ‣ DirectoriesPackagePrograms( name ) ( function )

returns a list of the bin/architecture subdirectories of all packages name where architecture is the architecture on which GAP has been compiled (this can be accessed as GAPInfo.Architecture, see GAPInfo (3.5-1)) and the version of the installed package coincides with the version of the package name that is already loaded or is currently going to be loaded or would be the first version GAP would try to load if no other version is explicitly prescribed. (If the package name is not yet loaded then we cannot guarantee that the returned directories belong to a version that really can be loaded.)

Note that DirectoriesPackagePrograms is likely to be called in the AvailabilityTest function in the package's PackageInfo.g file (see 76.3-11).

The directories returned by DirectoriesPackagePrograms are the place where external binaries of the GAP package name for the current package version and the current architecture should be located.

gap> DirectoriesPackagePrograms( "nq" );
[ dir("/home/gap/4.0/pkg/nq/bin/x86_64-unknown-linux-gnu-gcc/64-bit/"),
dir("/home/gap/4.0/pkg/nq/bin/x86_64-unknown-linux-gnu-gcc/") ]


##### 76.3-6 CompareVersionNumbers
 ‣ CompareVersionNumbers( supplied, required[, "equal"] ) ( function )

A version number is a string which contains nonnegative integers separated by non-numeric characters. Examples of valid version numbers are for example:

"1.0"   "3.141.59"  "2-7-8.3" "5 release 2 patchlevel 666"


CompareVersionNumbers compares two version numbers, given as strings. They are split at non-digit characters, the resulting integer lists are compared lexicographically. The routine tests whether supplied is at least as large as required, and returns true or false accordingly. A version number ending in dev is considered to be infinite.

 ‣ IsPackageMarkedForLoading( name, version ) ( function )

This function can be used in the code of a package A, say, for testing whether the package name in version version will be loaded after the LoadPackage (76.2-1) call for the package A has been executed. This means that the package name had been loaded before, or has been (directly or indirectly) requested as a needed or suggested package of the package A or of a package whose loading requested that A was loaded.

 ‣ DeclareAutoreadableVariables( pkgname, filename, varlist ) ( function )

Let pkgname be the name of a package, let filename be the name of a file relative to the home directory of this package, and let varlist be a list of strings that are the names of global variables which get bound when the file is read. DeclareAutoreadableVariables notifies the names in varlist such that the first attempt to access one of the variables causes the file to be read.

##### 76.3-9 Kernel modules in GAP packages

If the package has a kernel module, then it can be compiled using the gac script. A kernel module is implemented in C and follows certain conventions to comply with the GAP kernel interface, which we plan to document later. In the meantime, we advice to get in touch with GAP developers if you plan to develop such a package.

To use the gac script to produce dynamically loadable modules, call it with the -d option, for example:

\$ gap4/bin/i386-ibm-linux-gcc2/gac -d test.c


This will produce a file test.so, which then can be loaded into GAP with LoadDynamicModule (76.3-10).

 ‣ LoadDynamicModule( filename[, crc] ) ( function )

To load a compiled file, the command LoadDynamicModule is used. This command loads filename as module. If given, the CRC checksum crc must match the value of the module (see 9.7-7).

gap> LoadDynamicModule("./test.so");
gap> CrcFile("test.so");
2906458206
<function>( <arguments> ) called from read-eval-loop
you can 'quit;' to quit to outer loop, or
you can 'return;' to continue
brk> quit;


On some operating systems, once you have loaded a dynamic module with a certain filename, loading another with the same filename will have no effect, even if the file on disk has changed.

##### 76.3-11 The PackageInfo.g File

Each package has the file PackageInfo.g which contains meta-information about the package (package name, version, author(s), relations to other packages, homepage, download archives, banner, etc.). This file is used by the package loading mechanism and also for the distribution of a package to other users.

##### 76.3-12 ValidatePackageInfo
 ‣ ValidatePackageInfo( info ) ( function )

This function is intended to support package authors who create or modify PackageInfo.g files. (It is not called when these files are read during the startup of GAP or when packages are actually loaded.)

The argument info must be either a record as is contained in a PackageInfo.g file or a a string which describes the path to such a file. The result is true if the record or the contents of the file, respectively, has correct format, and false otherwise; in the latter case information about the incorrect components is printed.

Note that the components used for package loading are checked as well as the components that are needed for composing the package overview web page or for updating the package archives.

If info is a string then ValidatePackageInfo checks additionally whether those package files exist that are mentioned in the file info, for example the manual.six file of the package documentation.

##### 76.3-13 ShowPackageVariables
 ‣ ShowPackageVariables( pkgname[, version][, arec] ) ( function )
 ‣ PackageVariablesInfo( pkgname, version ) ( function )

Let pkgname be the name of a GAP package. If the package pkgname is available but not yet loaded then ShowPackageVariables prints a list of global variables that become bound and of methods that become installed when the package is loaded. (For that, GAP actually loads the package.)

If a version number version is given (see Section Example: Version Numbers) then this version of the package is considered.

An error message is printed if (the given version of) the package is not available or already loaded.

Information is printed about new and redeclared global variables, and about names of global variables introduced in the package that differ from existing globals only by case; note that the GAP help system is case insensitive, so it is difficult to document identifiers that differ only by case.

Info lines for undocumented variables are marked with an asterisk *.

The following entries are omitted from the list: default setter methods for attributes and properties that are declared in the package, and Setattr and Hasattr type variables where attr is an attribute or property.

The output can be customized using the optional record arec, the following components of this record are supported.

show

a list of strings describing those kinds of variables which shall be shown, such as "new global functions"; the default are all kinds that appear in the package,

showDocumented

true (the default) if documented variables shall be shown, and false otherwise,

showUndocumented

true (the default) if undocumented variables shall be shown, and false otherwise,

showPrivate

true (the default) if variables from the package's name space (see Section 4.10) shall be shown, and false otherwise,

Display

a function that takes a string and shows it on the screen; the default is Print (6.3-4), another useful value is Pager (2.4-1).

An interactive variant of ShowPackageVariables is the function BrowsePackageVariables (Browse: BrowsePackageVariables) that is provided by the GAP package Browse. For this function, it is not sensible to assume that the package pkgname is not yet loaded before the function call, because one might be interested in packages that must be loaded before Browse itself can be loaded. The solution is that BrowsePackageVariables (Browse: BrowsePackageVariables) takes the output of PackageVariablesInfo as its second argument. The function PackageVariablesInfo is used by both ShowPackageVariables and BrowsePackageVariables (Browse: BrowsePackageVariables) for collecting the information about the package in question, and can be called before the package Browse is loaded.

##### 76.3-14 BibEntry
 ‣ BibEntry( pkgname[, key] ) ( function )

Returns: a string in BibXMLext format (see GAPDoc: The BibXMLext Format) that can be used for referencing the GAP system or a GAP package.

If the argument pkgname is the string "GAP", the function returns an entry for the current version of GAP.

Otherwise, if a string pkgname is given, which is the name of a GAP package, an entry for this package is returned; this entry is computed from the PackageInfo.g file of the current version of the package, see InstalledPackageVersion (76.3-3). If no package with name pkgname is installed then the empty string is returned.

A string for a different version of GAP or a package can be computed by entering, as the argument pkgname, the desired record from the PackageInfo.g file. (One can access these records using the function PackageInfo.)

In each of the above cases, an optional argument key can be given, a string which is then used as the key of the BibTeX entry instead of the default key that is generated from the system/package name and the version number.

BibEntry requires the functions FormatParagraph (GAPDoc: FormatParagraph) and NormalizedNameAndKey (GAPDoc: NormalizedNameAndKey) from the GAP package GAPDoc.

The functions ParseBibXMLextString (GAPDoc: ParseBibXMLextString) and StringBibXMLEntry (GAPDoc: StringBibXMLEntry) can be used to create for example a BibTeX entry from the return value, as follows.

gap> bib:= BibEntry( "GAP", "GAP4.5" );;
gap> Print( bib, "\n" );
<entry id="GAP4.5"><misc>
<title><C>GAP</C> &ndash; <C>G</C>roups, <C>A</C>lgorithms,
and <C>P</C>rogramming, <C>V</C>ersion 4.5.1</title>
<howpublished><URL>http://www.gap-system.org</URL></howpublished>
<key>GAP</key>
<keywords>groups; *; gap; manual</keywords>
<other type="organization">The GAP <C>G</C>roup</other>
</misc></entry>
gap> parse:= ParseBibXMLextString( bib );;
gap> Print( StringBibXMLEntry( parse.entries[1], "BibTeX" ) );
@misc{ GAP4.5,
title =            {{GAP}   {\textendash}   {G}roups,   {A}lgorithms,  and
{P}rogramming, {V}ersion 4.5.1},
organization =     {The GAP {G}roup},
howpublished =     {\href                      {http://www.gap-system.org}
{\texttt{http://www.gap-system.org}}},
key =              {GAP},
keywords =         {groups; *; gap; manual}
}


generated by GAPDoc2HTML