Compaq Fortran
User Manual for
OpenVMS Alpha Systems


Previous Contents Index

10.2.4 Passing Arguments by Reference---%REF Function

The %REF function passes the argument by reference. It has the following form:

%REF(arg)

The argument-list entry generated by the compiler will contain the address of the argument (arg). The argument value can be a record name, a procedure name, or a numeric or character expression, array, character array section, or array element. In Compaq Fortran, passing by reference is the default mechanism for numeric values, so the %REF call is usually not needed.

10.2.5 Examples of Argument Passing Built-in Functions

The following examples demonstrate the use of the argument list built-in functions.

  1. In this example, the first constant is passed by reference. The second constant is passed by immediate value:


      CALL SUB(2,%VAL(2)) 
    

  2. In this example, the first character variable is passed by character descriptor. The second character variable is passed by reference:


      CHARACTER(LEN=10) A,B 
      CALL SUB(A,%REF(B)) 
    

  3. In this example, the first array is passed by reference. The second array is passed by descriptor:


      INTEGER IARY(20), JARY(20) 
      CALL SUB(IARY,%DESCR(JARY)) 
    

10.3 Using the cDEC$ ALIAS and cDEC$ ATTRIBUTES Directives

This section provides reference information about the following directives:

10.3.1 The cDEC$ ALIAS Directive

Compaq Fortran now supports the cDEC$ ALIAS directive in the same manner as Compaq Fortran 77. Use this directive to specify that the external name of an external subprogram is different from the name by which the calling procedure references it.

The syntax is:

cDEC$ ALIAS internal-name, external-name

The internal-name is the name of the subprogram as used in the current program unit.

The external-name is either a quoted character constant (delimited by single quotation marks) or a symbolic name.

If external-name is a character constant, the value of that constant is used as the external name for the specified internal name. The character constant is used as it appears, with no modifications for case. The default for the Compaq Fortran compiler is to force the name into uppercase.

If external-name is a symbolic name, the symbolic name (in uppercase) is used as the external name for the specified internal name. Any other declaration of the specified symbolic name is ignored for the purposes of the ALIAS directive.

For example, in the following program (free source form):


  PROGRAM ALIAS_EXAMPLE 
  !DEC$ ALIAS ROUT1, 'ROUT1A' 
  !DEC$ ALIAS ROUT2, 'routine2_' 
  !DEC$ ALIAS ROUT3, rout3A 
        CALL ROUT1 
        CALL ROUT2 
        CALL ROUT3 
  END PROGRAM ALIAS_EXAMPLE 

The three calls are to external routines named ROUT1A, routine2_, and ROUT3A. Use single quotation marks (character constant) to specify a case-sensitive name.

This feature can be useful when porting code to systems where different routine naming conventions are in use. By adding or removing the cDEC$ ALIAS directive, you can specify an alternate routine name without recoding the application.

10.3.2 The cDEC$ ATTRIBUTES Directive

Use the cDEC$ ATTRIBUTES directive to specify properties for data objects and procedures. These properties let you specify how data is passed and the rules for invoking procedures. The cDEC$ ATTRIBUTES directive is intended to simplify mixed-language calls with Compaq Fortran routines written in C or Assembler.

The cDEC$ ATTRIBUTES directive takes the following form:


 cDEC$ ATTRIBUTES att [,att]... :: object [,object]... 

In this form:

The Compaq Fortran Language Reference Manual explains the valid combinations of properties with the various types of objects.

The ATTRIBUTES properties are described in the following sections:

10.3.2.1 C Property

The C property provides a convenient way for Compaq Fortran to interact with routines written in C.

When applied to a subprogram, the C property defines the subprogram as having a specific set of calling conventions.

The C property affects how arguments are passed, as described in Table 10-1.

Table 10-1 C Property and Argument Passing
Argument Variable Type Fortran Default C Property Specified for Routine
Scalar (includes derived types) Passed by reference Passed by value (large derived type variables may be passed by reference)
Scalar, with VALUE specified Passed by value Passed by value
Scalar, with REFERENCE specified Passed by reference Passed by reference
String Passed by character descriptor Passes the first character of the string, padded to a full integer
String, with VALUE specified Error Passes the first character of the string, padded to a full integer
String, with REFERENCE specified Passed by reference Passed by reference
Arrays, including pointers to arrays Always passed by reference Always passed by reference

If C is specified for a subprogram, arguments (except for arrays and characters) are passed by value. Subprograms using standard Fortran conventions pass arguments by reference.

Character arguments are passed as follows:

Example 10-1 shows Compaq Fortran code that calls the C function pnst by using the cDEC$ ATTRIBUTES C directive and C language passing conventions.

Example 10-1 Calling C Functions and Passing Integer Arguments

! Using !DEC$ ATTRIBUTES to pass argument to C. File: pass_int_cdec.f90 
 
interface 
   subroutine pnst(i) 
     !DEC$ ATTRIBUTES C :: pnst 
     integer i 
   end subroutine 
end interface 
 
  integer :: i 
  i = 99 
  call pnst(i)             ! pass by value 
  print *,"99==",i 
end 

Example 10-2 shows the C function called pnst that is called by the example program shown in Example 10-1

Example 10-2 Calling C Functions and Passing Integer Arguments

/* get integer by value from Fortran. File: pass_int_cdec_c.c */ 
 
void pnst(int i) { 
    printf("99==%d\n",i); 
        i = 100; 
} 

The files (shown in Example 10-1 and Example 10-2) might be compiled, linked, and run as follows:


$ CC PASS_INT_CDEC_C.C
$ FORTRAN PASS_INT_CDEC.F90
$ LINK/EXECUTABLE=PASS_CDEC PASS_INT_CDEC, PASS_INT_CDEC_C
$ RUN PASS_CDEC
99==99 
99==          99

10.3.2.2 ALIAS Property

You can specify the ALIAS property as cDEC$ ALIAS or as cDEC$ ATTRIBUTES ALIAS; they are equivalent, except that using cDEC$ ALIAS allows symbol names (see Section 10.3.1).

The ALIAS property allows you to specify that the external name of an external subprogram is different from the name by which the calling procedure references it (see Section 10.3.1).

10.3.2.3 REFERENCE and VALUE Properties

The following cDEC$ ATTRIBUTES properties specify how a dummy argument is to be passed:

Character values, substrings, and arrays cannot be passed by value. When REFERENCE is specified for a character argument, the string is passed with no descriptor.

VALUE is the default if the C property is specified in the subprogram definition (for scalar data only).

Consider the following free-form example, which passes an integer by value:


  interface 
    subroutine foo (a) 
     !DEC$ ATTRIBUTES value :: a 
        integer a 
    end subroutine foo 
  end interface 

This subroutine can be invoked from Compaq Fortran using the name foo:


   integer i 
   i = 1 
   call foo(i) 
 
   end program 

This is the actual subroutine code:


    subroutine foo (i) 
     !DEC$ ATTRIBUTES value :: i 
        integer i 
        i = i + 1 
        . 
        . 
    end subroutine foo 

10.3.2.4 EXTERN and VARYING Properties

The EXTERN property specifies that a variable is allocated in another source file. EXTERN can be used in global variable declarations, but it must not be applied to dummy arguments.

You must use EXTERN when accessing variables declared in other languages.

The VARYING directive allows a variable number of calling arguments. If VARYING is specified, the C property must also be specified.

When using the VARYING directive, either the first argument must be a number indicating how many arguments to process, or the last argument must be a special marker (such as -1 ) indicating it is the final argument. The sequence of the arguments, and types and kinds, must be compatible with the called procedure.

For More Information:

See the Compaq Fortran Language Reference Manual.

10.3.2.5 ADDRESS64 Property

Specifies that the object has a 64-bit address. This property can be specified for any variable or dummy argument, including ALLOCATABLE and deferred-shape arrays. However, variables with this property cannot be data-initialized.

It can also be specified for COMMON blocks or for variables in a COMMON block. If specified for a COMMON block variable, the COMMON block implicitly has the ADDRESS64 property.

ADDRESS64 is not compatible with the AUTOMATIC attribute.

For More Information:

10.4 OpenVMS Procedure-Calling Standard

Programs compiled by the Compaq Fortran compiler conform to the standard defined for OpenVMS Alpha procedure calls (see the OpenVMS Programming Interfaces: Calling a System Routine and OpenVMS Calling Standard). This standard prescribes how registers and the system-maintained call stack can be used, how function values are returned, how arguments are passed, and how procedures receive and return control.

When writing routines that can be called from Compaq Fortran programs, you should give special consideration to the argument list descriptions in Section 10.4.3.

10.4.1 Register and Stack Usage

The Alpha architecture provides 32 general purpose integer registers (R0-R31) and 32 floating-point registers (F0-F31), each 64 bits in length. The OpenVMS Programming Interfaces: Calling a System Routine defines the use of these registers, as listed in Table 10-2.

Table 10-2 OpenVMS Alpha Register Usage
Register Use
R0 Function value return registers; also see F0, F1
R1 Conventional scratch register
R2-R15 Conventional saved registers
R16-R21 Argument registers (one register per argument, additional arguments are placed on the stack)
R22-R24 Conventional scratch registers
R25 Argument information (AI); contains argument count and argument type
R26 Return address (RA) register
R27 Procedure value (PV) register
R28 Volatile scratch register
R29 Frame pointer (FP)
R30 Stack pointer (SP)
R31 Read As Zero/Sink (RZ) register
PC Program counter (PC), a special register that addresses the instruction stream, which is not accessible as an integer register
F0, F1 Function value return registers (F1 is used for the imaginary part of COMPLEX)
F2-F9 Conventional saved registers
F10-F15 Conventional scratch registers
F16-F21 Argument registers (one per argument, additional arguments are placed on the stack)
F22-F30 Conventional scratch registers
F31 Read As Zero/Sink (RZ) register

A stack is defined as a LIFO (last-in/first-out) temporary storage area that the system allocates for every user process.

Each time you call a routine, the system places information on the stack in the form of procedure context structures, as described in OpenVMS Calling Standard.

10.4.2 Return Values of Procedures

A procedure is a Compaq Fortran subprogram that performs one or more computations for other programs. Procedures can be either functions or subroutines. Both functions and subroutines can return values by storing them in variables specified in the argument list or in common blocks.

A function, unlike a subroutine, can also return a value to the calling program by assigning the value to the function's name. The method that function procedures use to return values depends on the data type of the value, as summarized in Table 10-3.

Table 10-3 Function Return Values
Data Type Return Method
  • Logical
  • Integer
R0
REAL (KIND=4) F0
REAL (KIND=8) F0
REAL (KIND=16) F0 and F1
COMPLEX (KIND=4)
(COMPLEX*8)
F0 (real part), F1 (imaginary part)
COMPLEX (KIND=8)
(COMPLEX*16)
F0 (real part), F1 (imaginary part)
Character In addition to the arguments, an entry is added to the beginning of the argument list. This additional entry contains the address of the character string descriptor. At run time, before the call, the calling program allocates enough storage to contain the result and places the storage address in the descriptor.
Pointers R0 contains the address of the array descriptor (see Section 10.1.6).
Assumed-shape arrays,
Deferred-shape arrays
R0 contains the address of the array descriptor (see Section 10.1.5).

For More Information:

10.4.3 Argument Lists

Use an argument list to pass information to a routine and receive results.

The OpenVMS Calling Standard defines an argument list as an argument item sequence, consisting of the first six arguments occupying six integer and six floating-point registers (R16-R21 and F16-F21), with additional arguments placed on the stack. The argument information is contained in R25 (AI register). The stack pointer is contained in R30. For more details on argument lists, see the OpenVMS Calling Standard.

Memory for Compaq Fortran argument lists and for OpenVMS Alpha descriptors is allocated dynamically on the stack.

OpenVMS Alpha descriptors are generated from the use of the %DESCR function or by passing CHARACTER data, Fortran 90 pointers, and certain types of arrays (see Section 10.1.7).

Omitted arguments---for example, CALL X(A, ,B)---are represented by an argument passed by value that has a value of zero. This is a Compaq extension to the Fortran 90 standard.

Fortran optional arguments (OPTIONAL attribute) are also represented by an argument passed by value that has a value of zero.

For More Information:

On using Fortran language standards to specify arguments, see the Compaq Fortran Language Reference Manual.

10.5 OpenVMS System Routines

System routines are OpenVMS routines that perform common tasks, such as finding the square root of a number or allocating virtual memory. You can call any system routine from your program, provided that Compaq Fortran supports the data structures required to call the routine (in a FORSYSDEF library module) or you define them yourself.

The system routines used most often are OpenVMS Run-Time Library routines and system services. System routines are documented in detail in the OpenVMS Run-Time Library Routines Volume and the OpenVMS System Services Reference Manual.

10.5.1 OpenVMS Run-Time Library Routines

The OpenVMS Run-Time Library provides commonly-used routines that perform a wide variety of functions. These routines are grouped according to the types of tasks they perform, and each group has a prefix that identifies those routines as members of a particular OpenVMS Run-Time Library facility. Table 10-4 lists all of the language-independent Run-Time Library facility prefixes and the types of tasks each facility performs.

Table 10-4 Run-Time Library Facilities
Facility Prefix Types of Tasks Performed
CVT$ Library routines that handle floating-point data conversion
DTK$ DECtalk routines that are used to control Compaq's DECtalk device
LIB$ Library routines that:
  • Obtain records from devices
  • Manipulate strings
  • Convert data types for I/O
  • Allocate resources
  • Obtain system information
  • Signal exceptions
  • Establish condition handlers
  • Enable detection of hardware exceptions
  • Process cross-reference data
MATH$ Mathematics routines that perform arithmetic, algebraic, and trigonometric calculations
OTS$ General-purpose routines that perform such tasks as data type conversions as part of a compiler's generated code
PPL$ Parallel processing routines that help you implement concurrent programs on single-CPU and multiprocessor systems
SMG$ Screen-management routines that are used in designing, composing, and keeping track of complex images on a video screen
STR$ String manipulation routines that perform such tasks as searching for substrings, concatenating strings, and prefixing and appending strings

10.5.2 OpenVMS System Services Routines

System services are system routines that perform a variety of tasks, such as controlling processes, communicating among processes, and coordinating I/O.

Unlike the OpenVMS Run-Time Library routines, which are divided into groups by facility, all system services share the same facility prefix (SYS$). However, these services are logically divided into groups that perform similar tasks. Table 10-5 describes these groups.

Table 10-5 System Services
Group Types of Tasks Performed
AST Allows processes to control the handling of ASTs
Change Mode Changes the access mode of particular routines
Condition Handling Designates condition handlers for special purposes
Event Flag Clears, sets, reads, and waits for event flags, and associates with event flag clusters
Input/Output Performs I/O directly, without going through OpenVMS RMS
Lock Management Enables processes to coordinate access to shareable system resources
Logical Names Provides methods of accessing and maintaining pairs of character string logical names and equivalence names
Memory Management Increases or decreases available virtual memory, controls paging and swapping, and creates and accesses shareable files of code or data
Process Control Creates, deletes, and controls execution of processes
Process Information Returns information about processes
Security Enhances the security of OpenVMS systems
Timer and Time Conversion Schedules events, and obtains and formats binary time values

10.6 Calling Routines---General Considerations

The basic steps for calling routines are the same whether you are calling a routine written in Compaq Fortran, a routine written in some other OpenVMS language, a system service, or a Compaq Fortran RTL routine.

To call a subroutine, use the CALL statement.

To call a function, reference the function name in an expression or as an argument in another routine call.

In any case, you must specify the name of the routine being called and all non-optional arguments required for that routine. Make sure the data types and passing mechanisms for the actual arguments you are passing coincide with those declared in the routine (see Table 10-6 for information on OpenVMS data types or OpenVMS Programming Interfaces: Calling a System Routine for data types needed for mixed language programming).

If you do not want to specify a value for a required parameter, you can pass a null argument by inserting a comma (,) as a placeholder in the argument list. If the routine requires any passing mechanism other than the default, you must specify the passing mechanism in the CALL statement or the function call.

Example 10-3 shows an example that uses the LIB$GET_VM RTL routine and the Compaq Fortran 77 POINTER statement to allocate memory for an array. This example uses Compaq extensions (POINTER statement and LIB$ routine) to allocate virtual memory. The routine name varies with the operating system (LIB$GET_VM on OpenVMS systems and malloc on UNIX systems).

Example 10-3 illustrates calling an OpenVMS RTL LIB$ routine.

Example 10-3 Use of LIB$GET_VM and POINTER

! Program accepts an integer and displays square root values 
 
  INTEGER (KIND=4) N 
  READ (5,*) N            ! Request typed integer value 
  CALL MAT(N) 
  END 
 
! Subroutine MAT uses the typed integer value to display the square 
! root values of numbers from 1 to N (the typed number) 
 
  SUBROUTINE MAT(N)       
  REAL I(1000)           ! Fixed 1000 dimension allows bounds checking 
  INTEGER SIZE,STATUS 
  POINTER (P,I)          ! Compaq Fortran 77 POINTER statement establishes 
                         ! P as the pointer and array variable I as the 
                         ! pointee. P will receive memory base address 
                         ! from LIB$GET_VM. 
 
  SIZE=SIZEOF(I(1)) * N  ! Array I contains values calculated in loop below. 
                         ! Intrinsic SIZEOF returns size of memory 
                         ! to allocate. 
 
  STATUS = LIB$GET_VM(SIZE,P)    ! Allocate memory 
  IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS)) 
 
  DO J=1,N 
     I(J) = SQRT(FLOAT(J))   ! Intrinsic FLOAT converts integer to REAL. 
  ENDDO 
  TYPE *, (I(J),J=1,N)       ! Display calculated values 
 
  STATUS = LIB$FREE_VM(SIZE,P)   ! Deallocate memory 
  IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS)) 
 
  END SUBROUTINE MAT 

The following commands show how to compile, link, and run the program and how it displays the square root of numbers from 1 to 4 during execution:


$ FORTRAN SQUARE_ROOT
$ LINK SQUARE_ROOT
$ RUN SQUARE_ROOT
4
   1.000000       1.414214       1.732051       2.000000 

The call to LIB$GET_VM as a function reference allocates memory and returns the starting address in variable P. The return status (variable STATUS) is tested to determine whether an error should be signaled using a subroutine call to LIB$SIGNAL, passing the value of the variable status (not its address) using the %VAL built-in function.

For More Information:


Previous Next Contents Index