[OpenVMS documentation]
[Site home] [Send comments] [Help with this site] [How to order documentation] [OpenVMS site] [Compaq site]
Updated: 11 December 1998

OpenVMS Programming Interfaces: Calling a System Routine


Previous Contents Index

2.5.1 Passing Arguments by Value

When your program passes an argument using the by value mechanism, the argument list entry contains either the actual uninterpreted 32-bit VAX value or a 64-bit Alpha value (zero- or sign-extended) of the argument. For example, to pass the constant 100 by value, the calling program puts 100 directly in the argument list or sequence. For more information about passing 64-bit Alpha values, refer to the OpenVMS Alpha Guide to 64-Bit Addressing and VLM Features.

All high-level languages (except C) require you to specify the by-value mechanism explicitly when you call a procedure that accepts an argument by value. For example, FORTRAN uses the %VAL built-in function, while COBOL uses the BY VALUE qualifier on the CALL [USING] statement.

A FORTRAN program calls a procedure using the by-value mechanism as follows:


     INCLUDE  '($SSDEF)' 
     CALL LIB$STOP (%VAL(SS$_INTOVF)) 

A BLISS program calls this procedure as follows:


     LIB$SIGNAL (SS$_INTOVF) 

The equivalent VAX MACRO code is as follows:


     PUSHL    #SS$_INTOVF        ; Push longword by value 
     CALLS    #1,G^LIB$SIGNAL    ; Call LIB$SIGNAL 

A C language program calls a procedure using the by-value mechanism as follows:


 #include <starlet.h>         /* Declare the function*/ 
       . 
       . 
     enum  cluster0 
        { 
           completion, breakdown, beginning 
        }  event; 
 
     int status; 
     event = completion; 
       . 
       . 
     status = sys$setef(event);     /* Set event flag */ 

2.5.2 Passing Arguments by Reference

When your program passes arguments using the by reference mechanism, the argument list entry contains the address of the location that contains the value of the argument. For example, if variable x is allocated at location 1000, the argument list entry will contain 1000, the address of the value of x.

On Alpha processors, the address is sign-extended from 32 bits to 64 bits.

Most languages (but not C) pass scalar data by reference by default. Therefore, if you simply specify x in the CALL statement or function invocation, the language automatically passes the value stored at the location allocated to x to the OpenVMS system routine.

A VAX BLISS program calls a procedure using the by-reference mechanism as follows:


    LIB$FLT_UNDER (%REF(1)) 

The equivalent VAX MACRO code is as follows:


ONE:     .LONG    1                     ; Longword value 1 
           . 
           . 
           . 
         PUSHAL    ONE                  ; Push address of longword 
         CALLS    #1,G^LIB$FLT_UNDER    ; Call LIB$FLT_UNDER 

A C language program calls a procedure using the by-reference mechanism as follows:


 
 /*  This program shows how to call system service SYS$READEF.  */ 
 
 #include <ssdef.h> 
 #include <stdio.h> 
 
 #include <starlet.h>        /* Declare the function */ 
 
 main(void) 
 { 
                               /*  Longword that receives the status * 
                                *  of the event flag cluster         */ 
   unsigned cluster_status; 
 
   int return_status;          /* Status: SYS$READEF       */ 
 
                               /*  Argument values for SYS$READEF  */ 
   enum  cluster0 
      { 
         completion, breakdown, beginning 
      }  event; 
      . 
      . 
      . 
   event = completion;           /*  Event flag in cluster 0 */ 
 
                                 /*  Obtain status of cluster 0.  * 
                                  *  Pass value of event and      * 
                                  *  address of cluster_status.   */ 
 
   return_status =  SYS$READEF(event, &cluster_status); 
 
                                   /*  Check for successful call  */ 
   if (return_status != SS$WASCLR && return_status != SS$WASSSET) 
      { 
         /* Handle the error here.                             */ 
            . 
            . 
            . 
      } 
   else 
      { 
         /*  Check bits of interest in cluster_status here.    */ 
            . 
            . 
            . 
      } 
  } 
 

2.5.3 Passing Arguments by Descriptor

When a procedure specifies that an argument is passed by descriptor, the argument list entry must contain the address of a descriptor for the argument. For more information about OpenVMS Alpha 64-bit descriptors, refer to the OpenVMS Alpha Guide to 64-Bit Addressing and VLM Features.

On Alpha processors, the address is sign-extended from 32 bits to 64 bits.

This mechanism is used to pass more complicated data. For both Alpha and VAX systems, a descriptor includes at least the following fields:
Symbol Description
DSC$W_LENGTH Length of data (or DSC$W_MAXSTRLEN, maximum length, for varying strings)
DSC$B_DTYPE Data type
DSC$B_CLASS Descriptor class code
DSC$A_POINTER Address at which the data begins

The OpenVMS Calling Standard describes these fields in greater detail.

OpenVMS high-level languages include extensions for passing arguments by descriptor. When you specify by descriptor in these languages, the compiler creates the descriptor, defines its fields, and passes the address of the descriptor to the OpenVMS system routine. In some languages, by descriptor is the default passing mechanism for certain types of arguments, such as character strings. For example, the default mechanism for passing strings in BASIC is by descriptor.


    100    COMMON STRING GREETING = 30 
    200    CALL LIB$PUT_SCREEN(GREETING) 

The default mechanism for passing strings in COBOL, however, is by reference. Therefore, when passing a string argument to an OpenVMS system routine from a COBOL program, you must specify BY DESCRIPTOR for the string argument in the CALL statement.


    CALL LIB$PUT_OUTPUT USING BY DESCRIPTOR GREETING 

In VAX MACRO or BLISS, you must define the descriptor's fields explicitly and push its address onto the stack. Following is the VAX MACRO code that corresponds to the previous examples.


 
MSGDSC:    .WORD LEN                     ; DESCRIPTOR:  DSC$W_LENGTH 
           .BYTE DSC$K_DTYPE_T           ; DSC$B_DTYPE 
           .BYTE DSC$K_CLASS_S           ; DSC$B_CLASS 
           .ADDRESS MSG                  ; DSC$A_POINTER 
 
MSG:       .ASCII/Hello/                 ; String itself 
LEN = .-MSG                              ; Define the length of the string 
 
            .ENTRY  EX1,^M<> 
            PUSHAQ MSGDSC                ; Push address of descriptor 
            CALLS #1,G^LIB$PUT_OUTPUT    ; Output the string 
            RET 
            .END EX1 
 
 

The equivalent BLISS code looks like this:


MODULE BLISS1 (MAIN = BLISS1,      ! Example of calling LIB$PUT_OUTPUT 
        IDENT = '1-001', 
        ADDRESSING_MODE(EXTERNAL = GENERAL)) = 
BEGIN 
EXTERNAL ROUTINE 
    LIB$STOP,                   ! Stop execution via signaling 
    LIB$PUT_OUTPUT;             ! Put a line to SYS$OUTPUT 
 
FORWARD ROUTINE 
    BLISS1 : NOVALUE; 
 
LIBRARY 'SYS$LIBRARY:STARLET.L32'; 
 
ROUTINE BLISS1                  ! Routine 
        : NOVALUE = 
 
    BEGIN 
!+ 
! Allocate the necessary local storage. 
!- 
    LOCAL 
        STATUS,                         ! Return status 
        MSG_DESC : BLOCK [8, BYTE];     ! Message descriptor 
 
    BIND 
        MSG = UPLIT('HELLO'); 
 
!+ 
! Initialize the string descriptor. 
!- 
    MSG_DESC [DSC$B_CLASS] = DSC$K_CLASS_S; 
    MSG_DESC [DSC$B_DTYPE] = DSC$K_DTYPE_T; 
    MSG_DESC [DSC$W_LENGTH] = 5; 
    MSG_DESC [DSC$A_POINTER] = MSG; 
!+ 
! Put out the string.  Test the return status. 
! If it is not a success, then signal the RMS error. 
!- 
    STATUS = LIB$PUT_OUTPUT(MSG_DESC); 
    IF NOT .STATUS THEN LIB$STOP(.STATUS); 
    END;                ! End of routine BLISS1 
END                     ! End of module BLISS1 
ELUDOM 

A C language program calls a procedure using the by-descriptor mechanism as follows:


 /*  This program shows a call to system service SYS$SETPRN.    */ 
 
 #include <ssdef.h> 
 #include <stdio.h> 
                              /*  Define structures for descriptors */ 
 #include <descrip.h> 
 
 #include starlet.h            /*  Declare the function */ 
 
 int main(void) 
 { 
   int  ret;                  /*  Define return status of SYS$SETPRN  */ 
 
   struct  dsc$descriptor_s  name_desc;  /* Name the descriptor */ 
 
   char  *name =  "NEWPROC";             /* Define new process name */ 
      . 
      . 
      . 
   name_desc.dsc$w_length = strlen(name);  /* Length of name without * 
                                            * null terminator        */ 
 
   name_desc.dsc$a_pointer =  name; /* Put address of shortened string * 
                                     * in descriptor             */ 
 
   name_desc.dsc$b_class =  DSC$K_CLASS_S; /* String descriptor class */ 
 
   name_desc.dsc$b_dtype =  DSC$K_DTYPE_T; /* Data type: ASCII string */ 
      . 
      . 
      . 
   ret =  sys$setprn(&name_desc); 
 
   if (ret != SS$_NORMAL)          /*  Test return status      */ 
      fprintf(stderr, "Failed to set process name\n"), 
      exit(ret); 
      . 
      . 
      . 
 } 

2.6 Passing Scalars as Arguments

When you are passing an input scalar value to an OpenVMS system routine, you usually pass it either by reference or by value. You usually pass output scalar arguments by reference to OpenVMS system routines. An output scalar argument is the address of a location where some scalar output of the routine will be stored.

2.7 Passing Arrays as Arguments

Arrays are passed to OpenVMS system routines by reference or by descriptor.

Sometimes the routine knows the length and dimensions of the array to be received, as in the case of the table passed to LIB$CRC_TABLE. Arrays such as this are normally passed by reference.

In other cases, the routine actually analyzes and operates on the input array. The routine does not necessarily know the length or dimensions of such an input array, so a descriptor is necessary to provide the information the routine needs to describe the array accurately.

2.8 Passing Strings as Arguments

Strings are passed by descriptor to OpenVMS system routines. Table 2-5 lists the string-passing descriptors recognized by a system routine.

Table 2-5 String-Passing Descriptors
Descriptor Function Descriptor Class Code Numeric Value
Unspecified DSC$K_CLASS_Z 0
Fixed length (string/scalar) DSC$K_CLASS_S 1
Dynamic DSC$K_CLASS_D 2
Array DSC$K_CLASS_A 4
Scaled decimal DSC$K_CLASS_SD 9
Noncontiguous array DSC$K_CLASS_NCA 10
Varying length DSC$K_CLASS_VS 11

An OpenVMS system routine writes strings according to the following types of semantics:

2.9 Combinations of Descriptor Class and Data Type

Some combinations of descriptor class and data type are not permitted, either because they are not meaningful or because the calling standard does not recognize them. Possibly, the same function can be performed with more than one combination. This section describes the restrictions on the combinations of descriptor classes and data types. These restrictions help to keep procedure interfaces simple by allowing a procedure to accept a limited set of argument formats without sacrificing functional flexibility.

The tables in Figures 2-9, 2-10, and 2-11 show all possible combinations of descriptor classes and data types. For example, Figure 2-9 shows that your program can pass an argument to an OpenVMS system routine whose descriptor class is DSC$K_CLASS_A (array descriptor) and whose data type is unsigned byte (DSC$K_DTYPE_BU). The calling standard does not permit your program to pass an argument whose descriptor class is DSC$K_CLASS_D (dynamic string) and whose data type is unsigned byte.

A descriptor with data type DSC$K_DTYPE_DSC (24) points to a descriptor that has class DSC$K_CLASS_D (2) and data type DSC$K_DTYPE_T (14). All other class and data type combinations in the target descriptor are reserved for future definition in the standard.

The scale factor for DSC$K_CLASS_SD is always a decimal data type. It does not vary with the data type of the data described by the descriptor.

For DSC$K_CLASS_UBS and DSC$K_CLASS_UBA, the length field specifies the length of the data field in bits. For example, if the data type is unsigned word (DSC$K_DTYPE_WU), DSC$W_LENGTH equals 16.

Figure 2-9 Atomic Data Types and Descriptor Classes


Figure 2-10 String Data Types and Descriptor Classes


Figure 2-11 Miscellaneous Data Types and Descriptor Classes


2.10 Return of the Function Value

A function is a routine that returns a single value to the calling routine. The function value represents the value of the expression in the return statement. As specified by the calling standard, a function value may be returned as an actual value in R0.

On VAX systems, if the actual function value returned is greater than 32 bits, then both R0 and R1 should be used.

On Alpha systems, if the actual function returned is a floating-point value, the floating-point value is returned either in F0 or in both F0 and F1.

A standard function must return its function value by one of the following mechanisms:

These mechanisms are the standard return convention because they support the language-independent data types. For information about condition values returned in R0, see Section 2.11.

2.11 Return of the Condition Value

An OpenVMS system routine can indicate success or failure to the calling program by returning a condition value. In addition, an error condition to the calling program can return as a condition value in R0 or by error signaling.

A condition value in R0, also called a return status or completion code, is either a success (bit 0 = 1) value or an error condition (bit 0 = 0) value. In an error condition value, the low-order 3 bits specify the severity of the error (see Figure 2-12). Bits <27:16> contain the facility number, and bits <15:3> indicate the particular condition. Bits <31:28> are the control field. When the called procedure returns a condition value, the calling program can test R0 and choose a recovery path. A general guideline to follow when testing for success or failure is that all success codes have odd values and all error codes have even values.

Figure 2-12 Condition Value Format


When the completion code is signaled, the calling program must establish a handler to get control and take appropriate action. (See the OpenVMS Programming Concepts Manual or the OpenVMS Calling Standard for a description of signaling and condition handling and for more information about the condition value.)


Chapter 3
Calling Run-Time Library Routines

The OpenVMS Run-Time Library is a set of language-independent routines that establish a common run-time environment for user programs. The procedures ensure correct operation of complex language features and help enforce consistent operations on data across languages.

The OpenVMS Calling Standard describes the mechanisms used by OpenVMS languages for invoking routines and passing data between them. In effect, this standard describes the interface between your program and the run-time library routines that your program calls. This chapter describes the basic methods for coding calls to run-time library routines from an OpenVMS common language.

3.1 Overview

When you call a run-time library routine from your program, you must furnish whatever arguments the routine requires. When the routine completes execution, in most cases it returns control to your program. If the routine returns a status code, your program should check the value of the code to determine whether or not the routine completed successfully. If the return status indicates an error, you may want to change the flow of execution of your program to handle the error before returning control to your program.

When you log in, the operating system creates a process that exists until you log out. When you run a program, the system activates an executable image in your process. This image consists of a set of user procedures.

From the run-time library's point of view, user procedures are procedures that exist outside the run-time library and that can call run-time library routines. When you write a program that calls a run-time library routine, the run-time library views your program as a user procedure. User procedures also can call other user procedures that are either supplied by Digital or written by you. Because an OpenVMS native-mode language compiler program exists outside the run-time library, compiler-generated programs that call any run-time library routine are also defined as a set of user procedures.

The main program, or main procedure, is the first user procedure that the system calls after calling a number of initialization procedures. A user program consists of the main program and all of the other user procedures that it calls.

Figure 3-1 shows the calling relationships among a main program, other user procedures, library routines, and the operating system. In this figure, Call indicates that the calling procedures requested some information or action; Return indicates that the called procedure returned the information to the calling procedure or performed the action.

Figure 3-1 Calling the Run-Time Library


Although library routines can always call other library routines or the operating system, they can call user procedures only in the following cases:

3.2 Call Instructions

Each run-time library routine requires a specific calling sequence. This calling sequence indicates the elements that you must include when calling the routine, and the order of those elements. The form of a calling sequence first specifies the type of call being made. A library routine can be invoked by a CALL instruction or possibly by a JSB instruction (for VAX systems only) as follows:

On VAX systems, the following restrictions apply to the different types of calls:

3.2.1 Facility Prefix and Routine Name

Each routine is identified by a unique entry point name consisting of the facility prefix (for example, MTH$) and the procedure name (for example, MTH$SIN). Run-time library entry points follow the OpenVMS conventions for naming global symbols. A global entry point takes the following general form:

fac$symbol 

The elements that make up this format represent the following:
  fac A 2- or 3-character facility name
  symbol A 1- to 27-character symbol

The facility names are maintained in a systemwide Digital registry. A unique, 12-bit facility number is assigned to each facility name for use in (1) condition value symbols, and (2) condition values in procedure return status codes, signaled conditions, and messages. The high-order bit of this number is 0 for facilities assigned by Digital and 1 for those assigned by Application Project Services (APS) and customers. For further information, refer to the OpenVMS Calling Standard.

The run-time library facility names are as follows:
  CVT$ Convert routines
  DTK$ DECtalk routines
  LIB$ Library routines
  MTH$ Mathematics routines
  OTS$ General-purpose routines
  PPL$ Parallel processing routines
  SMG$ Screen management routines
  STR$ String-handling routines


Previous Next Contents Index

[Site home] [Send comments] [Help with this site] [How to order documentation] [OpenVMS site] [Compaq site]
[OpenVMS documentation]

Copyright © Compaq Computer Corporation 1998. All rights reserved.

Legal
5843PRO_003.HTML