The most current version of this document is available at http://www.flightlab.com/~joe/flightlab/firdef.html. A Postscript version is available at http://www.flightlab.com/~joe/flightlab/firdef.ps.
26 Jun 1998 The programs ffigen (see 3.2. ``FFIGEN'') and xfir (see 3.1. ``XFIR'') are available at ART in the IRIX 5 Flightlab working distribution (~wesley/bin); they are only available on herakles and the other IRIX 5 hosts. The sample Makefile in ~luther/misc/sample.Makefile has been updated with new rules to allow the integration of foreign functions into private versions of Scope.
Joe English
Last updated: Wednesday 08 March 2000, 09:55
A foreign function is a function or procedure written in a language other than Scope. At present, only Fortran language functions are supported by this interface.
To add user-defined external functions to the Scope parser, follow these steps:

In the interface definition file, comments are preceded by two slashes (//) and continue to the end of the line.
All keywords are case-insensitive.
It is possible to extract interface definition files from Fortran source code instead of writing them by hand; see 3.1. ``XFIR''.
External declarations specify the calling sequence of the Fortran subroutine and (optionally) the Scope language function interface.
External declarations have the following syntax:
extern extname ( extargs... )
[ interface ]
;
extname is the external procedure name. External names contain only alphanumeric characters and underscores, and must start with a letter. As in Fortran, names are case-insensitive.
extargs is a list of all the procedure arguments, separated by commas. The type, size, and direction of each argument must be specified. The syntax of each argument declaration is:
type argname [ ( dimensions ) ] direction
type must be INTEGER or REAL. INTEGER corresponds to the Fortran INTEGER type, and REAL corresponds to the Fortran DOUBLE PRECISION type. LOGICAL, CHARACTER, and COMPLEX types are not supported, nor are types with length specifiers (e.g., REAL*4, INTEGER*2).
dimensions is a comma-separated list of the array bounds. If omitted, the parameter is taken to be a scalar.
Each dimension may be specified as an integer constant, a variable name, or an expression built up from variables, constants, and + and * operators. The usual precedence rules for + and * apply.
Variable names used in dimension declarations need not be procedure parameters. If they are, they must be declared as INTEGER, scalar, and IN.
dimensions ::= dimension [ , dimension ... ] dimension ::= argname | integer | dimension + dimension | dimension * dimension | ( dimension )
direction is one of the following:
The INTERFACE section, if present, specifies the Scope language calling sequence:
interface ::=
INTERFACE [ outputs ] = name ( inputs )
If the function is a component method implementation, the INTERFACE section takes the following form instead:
interface ::=
INTERFACE class-name :: method-name
The INTERFACE section may be omitted if the external function should not be callable directly from Scope.
Multiple INTERFACE specifications are allowed. (This is useful when several different components have identical method implementations.)
For example,
extern "fortran" crsprd(real x(3) in, real y(3) in, real z(3) out) interface z = cross(x,y) ;
It is necessary to fully declare all dimensions of array parameters. The Fortran idiom of declaring only the leading dimension(s) and using 1 or * for the last dimension will not work, since the wrapper function checks the actual array bounds for all arguments in order to keep track of memory allocation.
NOTE --In Scope, the ``leading dimension'' of an array is always the same as its actual size.
NOTE --For Scope, arrays are limited to two dimensions.
The xfir command extracts interface definitions directly from Fortran source code. The resulting interface definition file is then processed by ffigen.
Usage:
xfir [ options... ] filename.f... > outfile.fir
Special comments in the Fortran source code are used to supply the extra information needed. Any line beginning with C. (capital letter `C' followed by a period) is interpreted as an xfir directive. Most directives are used to specify the modes of the parameters (input, output, or in/out). The rest of the information needed -- the name, type, and dimensions of each argument and their order in the calling sequence -- is extracted directly from the source code.
Available directives are:
xfir supports !-style inline comments, and continuation lines are handled properly. All Fortran code is folded to upper-case before processing.
Do not include any text beyond column 72 in input files; the Fortran compiler ignores it but mkfir does not. Hard tab characters will also confuse mkfir.
Only one parameter may be declared per line. That is, declarations the following are not allowed:
C.INPUT
DOUBLE PRECISION X(3), Y(3) ! Illegal!
The ffigen program generate wrapper functions and/or .CDF files from interface definition files,
Usage:
ffigen -o filename.c filename.fir ffigen -c filename.cdf filename.fir
... TBD
... not yet implemented
C Example foreign function.
C
C
SUBROUTINE MVMA(A,M,N, ALPHA, BETA, X, Y)
C
C.INTERFACE: y = mvma(a, alpha, beta, x, y)
C
C MVMA performs a weighted matrix-vector multiply and add,
C
C Y <- alpha*A*X + beta*Y
C
C.INPUT
INTEGER M ! rows of A, length of y
INTEGER N ! cols of A, length of x
DOUBLE PRECISION ALPHA ! weighting factor for A*X
DOUBLE PRECISION BETA ! weighting factor for Y
DOUBLE PRECISION A(M,N) ! input matrix
DOUBLE PRECISION X(N) ! input vector
C.INOUT
DOUBLE PRECISION Y(M) ! On output, y=y_old*beta+alpha*A*x
C.LOCAL
INTEGER I,J
C
C Begin subroutine:
C
DO I=1,N
Y(I) = BETA * Y(I)
DO J=1,N
Y(I) = Y(I) + ALPHA * A(I,J) * X(J)
END DO
END DO
RETURN
END
Running this through xfir produces the following:
// Generated Wed 08 Mar 2000, 09:54 PST
// MVMA
// xmp2.f, line 7
extern "fortran" MVMA(
real A(M,N) in,
integer M in,
integer N in,
real ALPHA in,
real BETA in,
real X(N) in,
real Y(M) in out)
interface y = mvma(a, alpha, beta, x, y)
;
For the Scope interface, only DOUBLE PRECISION and INTEGER variables are supported. DOUBLE PRECISION variables may have no more than two dimensions.
INTEGER parameters must be scalar inputs. It is not necessary (or permitted) to specify an integer parameter in the Scope language calling sequence; they may only appear as the array bound in a subsequent variable declaration.
Variadic functions (those taking a variable number of inputs) are not supported. If a function is called with fewer outputs than it returns, later arguments are simply ignored. It is not possible for a function to perform a different computation based on the number of output arguments.
Functions may not return variable-length arrays. That is, the size of all output parameters must be determined by the sizes of the input parameters. This means that functions like FIND cannot be defined with this interface.
The Fortran COMPLEX and CHARACTER data types are not supported. DOUBLE PRECISION and INTEGER are the only valid data types.
If complex arguments are passed to the generated functions, the imaginary part is silently ignored.
1-dimensional arguments must be passed in as column vectors (N by 1, not 1 by N).
FFIGEN diagnostics are not very good at the moment. Unknown types and modes are typically reported as syntax errors, and other errors are often reported as assertion failures followed by a coredump.