Performs tasks specified in subprograms supplied by the user, but not linked into Genstat; this directive may not be available on some computers.
||Filename of external executable program library and entry point function; default
||Structures whose values are to be passed to the external program, and returned|
||Reports any errors in the external program|
On some computers, you can arrange that one program, such as Genstat, calls for another to be executed, with information passed directly between the two. You can thus cause Genstat to execute your own subprograms without having to modify Genstat in any way. You can do this with the
PASS directive. To find out if the
PASS directive has been implemented in your version, you can either look at local documentation, or issue the
PASS command with no options or parameters. If it is not available, you will get a message saying that
PASS has not been implemented. You could then use the
SUSPEND directive instead.
To use the
PASS directive, you must first compile a program library file (DLL on Windows or SO on Linux) of your own code. You will need to program the reading and writing of the data to communicate with Genstat within the functions that are called. The details are explained below.
NAME option specifies the file name of a program library (DLL for Windows or SO for Linux) and a function name within the library, separated by a dollar symbol $. If the file extension is missing,
.DLL will be appended for Windows and
.SO will be appended for Linux. An advantage of omitting a file extension is that, if you have libraries that just differ in their extensions, the same command could be run on Windows and Linux. If no path is provided for the library, the system will search the Genstat Bin folder first, and then the folders in the
PATH environment variable. An
20 fault will be given if the library is not found. The library is then searched for an exported function with the name specified after the dollar (this is case sensitive). If no function name is provided, the function
GNPASS is used. An
21 fault is given if the function is not found.
You can use the
DATA pointer to pass the values of any data structures except texts. All the structures needed by your subprograms must be combined in a pointer structure, unless only one structure is needed. The structures must have values before you include them in a
PASS statement; if you want to use some of the structures to store results from your subprograms, you must initialize them to some arbitrary values, such as zero or missing. If you specify several pointers in a
PASS statement, your subprograms will be invoked several times, to deal in turn with the set of structures stored by each pointer. However, the values of the structures in all the pointers are copied before any work is done by your subprograms. Thus, if you want to operate with
PASS on the results of a previous operation by
PASS, you must give two
PASS statements with one pointer each rather than one statement with two pointers. The
ERROR parameter can pass a scalar value back into Genstat to indicate whether any errors have occurred.
As an example, consider using
PASS to carry out a simple transformation of a variate, as would be done by the statement
CALCULATE W = M*(V+S)**2
W are variates, and
S are scalars. Example
GNPASS programs which calculate this transformation in Fortran (
GENPASS.f90) and C (
GNPASSC.c) are available is the
Source directory of the Genstat installation. The functions in Fortran must have arguments
(INFILE, OUTFILE) of type
CHARACTER(*) and in C
(INFILE, OUTFILE, INLEN, OUTLEN) with the first two arguments of type char * and the last two of type int.
INFILE gives the filename of the input data and
OUTFILE gives the filename of the output to be read into Genstat. The extra C arguments are the lengths of the first two arguments. The example files contain a function
SQUARE that calculates the transformation. The code needs to handle missing values by comparing data with the missing value indicators given in
INFILE. Compiled versions of these for Windows (
GNPASSC.dll) are also in the Source folder. To create your own library you can use these as a template, replace
SQUARE with your own function, and then compile and link the code into a program library. To use the Fortran example, run the following statements:
SCALAR S,M; VALUE=2,10
VARIATE V,W; VALUES=!(1...10),!(10(*))
TEXT Lib; VALUE='%GENDIR%/Source/GNPASS$GNPASS'
PASS [NAME=Lib] !p(V,S,M,W)
PASS statement causes the program to run, and assigns the calculated values to the variate
W. To use the C program you would use
GNPASSC as the library.
Numbers can be used in place of scalars, as usual in Genstat statements:
PASS [NAME='%GENDIR%/Source/GNPASS$GNPASS'] !P(V,2,10,W)
To transform the values in both
V, as above, and another variate
X, with values 10…50 say, you could give the extra statements:
VARIATE X,Y; VALUES=!(10...50),!(50(*))
PASS [NAME=Lib] !p(V,2,10,W),!p(X,2,10,Y)
After preparing the Fortran or C program, you need to form it into an executable program, using a Fortran or C compiler. It may also be possible to use other source languages, provided the input and output formats of their compilers are compatible with that used by Genstat. All floating point values are passed from Genstat as type
REAL*8 for Fortran or
double for C. Factors and other items are passed as
INTEGER for Fortran or
int (4 bytes) for C. The
GNPASS programs loop around the pointers, with the number of pointers (an integer) provided as the first value in the
INFILE file. The next 3 items in the input file are the missing value representation for reals (given twice for historical reasons) and integers. Then there are sets of values for each pointer: the number of structures passed, and then the lengths of the arrays of type double precision, single precision (this is not used and should be zero) and integer. Then, for each structure in turn, the file contains its length, mode, Genstat origin and maximum block size (all integers) and its data. The Genstat origin is not used within the program, but should be written back to the result file. The maximum block size is no longer needed, as the files are not now written with a record structure but in unformatted binary mode. However, it must also be written to the result file. The Fortran program reads and writes the data in blocks, but the C program just uses single statements for this. The data are in double precision for mode 2 or integer for mode 3. The results must be written to the
OUTFILE file in the same format, other than that the number of pointers is replaced by an integer error code (0 for success) which is returned in the
ERROR parameter, and the missing values indicators are omitted. The example programs read the real and integer data into a single array with a calculated offset for each structure, and pass this in a common block/global structure. However, the data could be saved into individual structures and passed as arguments to the subroutine in your own program.
Commands for: Program control.