1. Home
  2. PASS directive

PASS directive

Performs tasks specified in subprograms supplied by the user, but not linked into Genstat; this directive may not be available on some computers.


NAME = text Filename of external executable program library and entry point function; default 'GNPASS$GNPASS'


DATA = pointers Structures whose values are to be passed to the external program, and returned
ERROR = scalars 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.

The 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 FI 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 FI 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


where V and W are variates, and M 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 (GNPASS.dll and 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:

VARIATE V,W; VALUES=!(1...10),!(10(*))
PASS [NAME=Lib] !p(V,S,M,W)

The 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:


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.

Option: NAME.
Parameters: DATA, ERROR.

See also

Directive: SUSPEND.

Commands for: Program control.

Updated on February 17, 2022

Was this article helpful?