Document revision date: 19 July 1999
[Compaq] [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]
[OpenVMS documentation]

OpenVMS Programming Interfaces: Calling a System Routine


Previous Contents Index

4.4.4 Testing the Condition Value

Each language provides some mechanism for testing the return status. Often you need only check the low-order bit, such as by a test for TRUE (success or informational return) or FALSE (error or warning return). Condition values that are returned by system services can provide information in addition to whether the service completed successfully. The condition value that usually indicates success is SS$_NORMAL, but others are defined. For example, the condition value SS$_BUFFEROVF, which is returned when a character string returned by a service is longer than the buffer provided to receive it, is a success code. This condition value, however, gives the program additional information.

Warning returns and some error returns indicate that the service performed some, but not all, of the requested function.

The possible condition values that each service can return are described with the individual service descriptions in the OpenVMS System Services Reference Manual. When you write calls to system services, read the descriptions of the return condition values to determine whether you want the program to check for particular return conditions.

To check the entire value for a specific return condition, each language provides a way for your program to determine the values associated with specific symbolically defined codes. You should always use these symbolic names when you write tests for specific conditions.

For information about how to test for these codes, see the user's guide for your programming language.

4.4.5 Special Condition Values Using Symbolic Codes

Individual services have symbolic codes for special return conditions, argument list offsets, identifiers, and flags associated with these services. For example, the Create Process (SYS$CREPRC) system service (which is used to create a subprocess or a detached process) has symbolic codes associated with the various privileges and quotas you can grant to the created process.

The SYS$LIBRARY:SYS$LIB_C.TLB file contains the C header files for OpenVMS Alpha C data structures and definitions. For more information about SYS$LIBRARY:SYS$LIB_C.TLB, refer to Chapter 5.

The default system macro library, STARLET.MLB, contains the macro definitions for most system symbols. When you assemble a source program that calls any of these macros, the assembler automatically searches STARLET.MLB for the macro definitions. Each symbol name has a numeric value.

If your language has a method of obtaining values for these symbols, this method is explained in the user's guide.

If your language does not have such a method, you can do the following:

  1. Write a short VAX MACRO program containing the desired macros.
  2. Assemble or compile the program and generate a listing. Using the listing, find the desired symbols and their hexadecimal values.
  3. Define each symbol with its value within your source program.

For example, to use the Get Job/Process Information ($GETJPI) system service to find out the accumulated CPU time (in 10-millisecond ticks) for a specified process, you must obtain the value associated with the item identifier JPI$_CPUTIM. You can do this in the following way:

  1. Create the following three-line VAX MACRO program (named JPIDEF.MAR here; you can choose any name you want):


    .TITLE  JPIDEF  "Obtain values for $JPIDEF" 
    $JPIDEF GLOBAL          ; These MUST be UPPERCASE 
    .END 
    

  2. Assemble and link the program to create the file JPIDEF.MAP as follows:


    $ MACRO JPIDEF
    $ LINK/NOEXE/MAP/FULL  JPIDEF
    %LINK-W-USRTFR, image NL:[].EXE; has no user transfer address
    

    The file JPIDEF.MAP contains the symbols defined by $JPIDEF listed both alphabetically and numerically.
    To compile the program to create the JPIDEF.MAP, enter the following:


    $ MACRO/MIGRATION JPIDEF
    $ LINK/NOEXE/MAP/FULL  JPIDEF
    %LINK-W-USRTFR, image NL:[].EXE; has no user transfer address
    

  3. Find the value of JPI$_CPUTIM and define the symbol in your program.

4.4.6 Testing the Return Condition Value for Assembly Languages

To check for successful completion after a system service call, the program can test the low-order bit of R0 and branch to an error-checking routine if this bit is not set, as follows:


    BLBC    R0,errlabel             ; Error if low bit clear 

Programs should not test for success by comparing the return status to SS$_NORMAL. A future release of OpenVMS may add new, alternate success codes to an existing service, causing programs that test for SS$_NORMAL to fail.

The error-checking routine may check for specific values or for specific severity levels. For example, the following VAX MACRO instruction checks for an illegal event flag number error condition:


    CMPL    #SS$_ILLEFC,R0        ; Is event flag number illegal? 

Note that return condition values are always longword values; however, all system services always return the same value in the high-order word of all condition values returned in R0.

4.4.7 System Messages Generated by Condition Values

When you execute a program with the DCL command RUN, the command interpreter uses the contents of R0 to issue a descriptive message if the program completes with an unsuccessful status.

The following VAX MACRO code fragment shows a simple error-checking procedure in a main program:


        $READEF_S - 
                EFN=#64, - 
                STATE=TEST 
        BSBW    ERROR 
         . 
         . 
         . 
ERROR:  BLBC    R0,10$          ; Check register 0 
        RSB                     ; Success, return 
10$:    RET                     ; Exit with R0 status 

After a system service call, the BSBW instruction branches to the subroutine ERROR. The subroutine checks the low-order bit in register 0 and, if the bit is clear, branches to a RET instruction that causes the program to exit with the status of R0 preserved. Otherwise, the subroutine issues an RSB instruction to return to the main program.

If the event flag cluster requested in this call to $READEF is not currently available to the process, the program exits and the command interpreter displays the following message:


%SYSTEM-F-UNASEFC, unassociated event flag cluster 

The keyword UNASEFC in the message corresponds to the condition value SS$_UNASEFC.

The following three severe errors generated by the calls, not the services, can be returned from calls to system services.
Error Meaning
SS$_ACCVIO The argument list cannot be read by the caller (using the $ name_G macro), and the service is not called.

This meaning of SS$_ACCVIO is different from its meaning for individual services. When SS$_ACCVIO is returned from individual services, the service is called, but one or more arguments to the service cannot be read or written by the caller.

SS$_INSFARG Not enough arguments were supplied to the service.
SS$_ILLSER An illegal system service was called.

4.5 Program Examples with System Service Calls

This section provides code examples that illustrate the use of a system service call in the following programming languages:

Example 4-2 System Service Call in Ada

with SYSTEM, TEXT_IO, STARLET, CONDITION_HANDLING;  (1)
procedure ORION is 
    -- Declare variables to hold equivalence name and length 
    -- 
    EQUIV_NAME: STRING (1..255);  (2)
    pragma VOLATILE (EQUIV_NAME);  
    NAME_LENGTH: SYSTEM.UNSIGNED_WORD; 
    pragma VOLATILE (NAME_LENGTH); 
 
    -- Declare itemlist and fill in entries. 
    -- 
    ITEM_LIST: STARLET.ITEM_LIST_3_TYPE (1..2) :=  (3)
        (1 => 
            (ITEM_CODE   => STARLET.LNM_STRING,  (4)
             BUF_LEN     => EQUIV_NAME'LENGTH, 
             BUF_ADDRESS => EQUIV_NAME'ADDRESS, 
             RET_ADDRESS => NAME_LENGTH'ADDRESS), 
         2 => 
            (ITEM_CODE   => 0, 
             BUF_LEN     => 0, 
             BUF_ADDRESS => SYSTEM.ADDRESS_ZERO, 
             RET_ADDRESS => SYSTEM.ADDRESS_ZERO)); 
 
    STATUS: CONDITION_HANDLING.COND_VALUE_TYPE;  (5)
 
begin 
    -- Translate the logical name 
    -- 
    STARLET.TRNLNM (   (6)
     STATUS => STATUS, 
     TABNAM => "LNM$FILE_DEV", 
     LOGNAM => "CYGNUS", 
     ITMLST => ITEM_LIST); 
 
    -- Display name if success, else signal error 
    -- 
    if not CONDITION_HANDLING.SUCCESS (STATUS) then   (7)
     CONDITION_HANDLING.SIGNAL (STATUS); 
    else 
        TEXT_IO.PUT ("CYGNUS translates to """); 
        TEXT_IO.PUT (EQUIV_NAME (1..INTEGER(NAME_LENGTH))); 
        TEXT_IO.PUT_LINE (""""); 
    end if; 
end ORION; 

Ada Notes

  1. The with clause names the predefined packages of declarations used in this program. SYSTEM and TEXT_IO are standard Ada packages; STARLET defines the OpenVMS system service routines, data types, and constants; and CONDITION_HANDLING defines error-handling facilities.
  2. Enough space is allocated to EQUIV_NAME to hold the longest possible logical name. NAME_LENGTH will receive the actual length of the translated logical name. The VOLATILE pragma is required for variables that will be modified by means other than an assignment statement or being an output parameter to a routine call.
  3. ITEM_LIST_3_TYPE is a predeclared type in package STARLET that defines the OpenVMS three-longword item list structure.
  4. The dollar-sign character is not valid in Ada identifiers; package STARLET defines the fac$ names by removing the dollar sign.
  5. COND_VALUE_TYPE is a predeclared type in package CONDITION_HANDLING that is used for return status values.
  6. System services are defined in package STARLET using names that omit the prefix SYS$. The passing mechanisms are specified in the routine declaration in STARLET, so they need not be specified here.
  7. In this example, any failure status from the SYS$TRNLNM service is signaled as an error. Other means of error recovery are possible; see your Ada language documentation for more details.

Example 4-3 System Service Call in BASIC

10  SUB ORION          (1)              ! Subprogram ORION 
 
    OPTION TYPE=EXPLICIT                ! Require declaration of all 
                                        ! symbols 
 
    EXTERNAL LONG FUNCTION SYS$TRNLNM   ! Declare the system service 
    EXTERNAL WORD CONSTANT LNM$_STRING  ! The request code that 
                                        ! we will use 
    DECLARE WORD NAMLEN,        (2)     ! Word to receive length 
            LONG SYS_STATUS             ! Longword to receive status 
    COMMON (BUF) STRING NAME_STRING = 255  (3)
 
    RECORD ITEM_LIST                    ! Define item 
                                        ! descriptor structure 
        WORD BUFFER_LENGTH              ! The buffer length 
        WORD ITEM                       ! The request code 
        LONG BUFFER_ADDRESS             ! The buffer address 
        LONG RETURN_LENGTH_ADDRESS      ! The address of the return len 
                                        ! word 
        LONG TERMINATOR                 ! The terminator 
    END RECORD ITEM_LIST                ! End of structure definition 
 
    DECLARE ITEM_LIST ITEMS             ! Declare an item list 
    ITEMS::BUFFER_LENGTH = 255%         ! Initialize the item list 
    ITEMS::ITEM = LNM$_STRING 
    ITEMS::BUFFER_ADDRESS = LOC( NAME_STRING ) 
    ITEMS::RETURN_LENGTH_ADDRESS = LOC( NAMLEN ) 
    ITEMS::TERMINATOR = 0 
                                 (4)
    SYS_STATUS = SYS$TRNLNM( , 'LNM$FILE_DEV', 'CYGNUS',, ITEMS) (5)
 
    IF (SYS_STATUS AND 1%) = 0% (6)
    THEN 
        ! Error path 
    ELSE 
        ! Success path 
    END IF 
    END SUB 
 
 

BASIC Notes

  1. The SUB statement defines the routine and its entry mask.
  2. The DECLARE WORD NAMLEN declaration reserves a 16-bit word for the output value.
  3. The COMMON (BUF) STRING NAME_STRING = 255 declaration allocates 255 bytes for the output data in a static area. The compiler builds the descriptor.
  4. The SYS$ form invokes the system service as a function.
    Enclose the arguments in parentheses and specify them in positional order only. Specify a comma for each optional argument that you omit (including trailing arguments).
  5. The input character string is specified directly in the system service call; the compiler builds the descriptor.
  6. The IF statement performs a test on the low-order bit of the return status. This form is recommended for all status returns.

Example 4-4 System Service Call in BLISS

MODULE ORION= 
 
BEGIN 
EXTERNAL ROUTINE 
    ERROR_PROC: NOVALUE;                 ! Error processing routine 
 
LIBRARY 'SYS$LIBRARY:STARLET.L32';       ! Library containing OpenVMS 
                                         ! macros (including $TRNLNM). 
                                         ! This declaration 
                                         ! is required. 
 
GLOBAL ROUTINE ORION: NOVALUE= 
 
    BEGIN 
    OWN 
        NAMBUF : VECTOR[255, BYTE],       ! Output buffer 
        NAMLEN : WORD,                    ! Translated string length 
        ITEMS : BLOCK[16,BYTE] 
                INITIAL(WORD(255,         ! Output buffer length 
                        LNM$_STRING),     ! Item code 
                        NAMBUF,           ! Output buffer 
                        NAMLEN,           ! Address of word for 
                                          ! translated 
                                          ! string length 
                        0);               ! List terminator 
 
    LOCAL                                 ! Return status from 
        STATUS;                           ! system service 
 
    STATUS = $TRNLNM(TABNAM = %ASCID'LNM$FILE_DEV', 
                     LOGNAME = %ASCID'CYGNUS', 
                     ITMLST = ITEMS); (1)
 
    IF NOT .STATUS THEN ERROR_PROC(.STATUS);  (2)
 
    END; 

BLISS Notes

  1. The macro is invoked by its service name, without a suffix.
    Enclose the arguments in parentheses and specify them by keyword. (Keyword names correspond to the names of the arguments shown in lowercase in the system service format descriptions in the OpenVMS System Services Reference Manual.)
  2. The return status, which is assigned to the variable STATUS, is tested for TRUE or FALSE. FALSE (low bit = 0) indicates failure or warning.

Example 4-5 System Service Call in C

 #include <starlet.h> (1)
 #include <lib$routines.h> 
 #include <ssdef.h> 
 #include <lnmdef.h> 
 #include <descrip.h> 
 #include <stdio.h> 
 
 typedef struct {                 (2)
     unsigned short  buffer_length; 
     unsigned short  item_code; 
     char     *buffer_addr; 
     short     *return_len_addr; 
     unsigned     terminator; 
 } item_list_t; 
 
 
 main () 
 {                                          (3)
     $DESCRIPTOR(table_name, "LNM$FILE_DEV"); 
     $DESCRIPTOR(log_name, "CYGNUS"); 
     char    translated_name[255]; 
     int     status; 
     short   return_length; 
     item_list_t item_list; 
 
     item_list.buffer_length = sizeof(translated_name); (4)
     item_list.item_code = LNM$_STRING; 
     item_list.buffer_addr = translated_name; 
     item_list.return_len_addr = &return_length; 
     item_list.terminator = 0; 
 
     status = sys$trnlnm(0, &table_name, &log_name, 0, &item_list);  (5)
 
     if (!(status & 1))       (6)
         lib$signal(status); 
     else 
         printf("The logical name %s is equivalent to %*s\n", 
             log_name.dsc$a_pointer, 
             return_length, 
             translated_name); 
 } 
 

C Notes

  1. The C language header file starlet.h defines OpenVMS system services entry points. The file lib$routines.h declares the LIB$ Run-Time Library routines.
  2. The structure of an item list entry is defined.
  3. The $DESCRIPTOR macro declares and initializes a character string descriptor. Here, two descriptors are created for use with the sys$trnlnm system service.
  4. The function sizeof is used to obtain the size of the string. The returned length will be stored as a short integer in return_length.
  5. The sys$trnlnm routine is defined in starlet.h.
  6. The IF statement performs a logical test following the function reference to determine whether the service completed successfully. If an error or warning occurs during the service call, the error is signaled.

Example 4-6 System Service Call in COBOL

IDENTIFICATION DIVISION. 
PROGRAM-ID. ORION.    (1)
ENVIRONMENT DIVISION. 
DATA DIVISION. 
WORKING-STORAGE SECTION. 
01 TABNAM PIC X(11) VALUE "LNM$FILE_DEV". 
01 CYGDES PIC X(6) VALUE "CYGNUS". 
01 NAMDES PIC X(255) VALUE SPACES.  (2)
01 NAMLEN PIC S9(4) COMP. 
01 ITMLIS. 
   02 BUFLEN PIC S9(4) COMP VALUE 225. 
   02 ITMCOD PIC S9(4) COMP VALUE 2.  (3)
   02 BUFADR POINTER VALUE REFERENCE NAMDES. 
   02 RETLEN POINTER VALUE REFERENCE NAMLEN. 
   02 FILLER PIC S9(5) COMP VALUE 0. 
01 RESULT PIC S9(9) COMP.   (4)
 
PROCEDURE DIVISION. 
START-ORION. 
    CALL "SYS$TRNLNM"   (5)
      USING OMITTED 
            BY DESCRIPTOR TABNAM 
            BY DESCRIPTOR CYGDES  (6)
            OMITTED 
            BY REFERENCE ITMLIS 
      GIVING RESULT. 
    IF RESULT IS FAILURE    (7)
       GO TO ERROR-CHECK. 
    DISPLAY "NAMDES:  ", NAMDES(1:NAMLEN). 
    GO TO THE-END. 
ERROR-CHECK. 
    DISPLAY "Returned Error: ", RESULT CONVERSION. 
THE-END. 
    STOP RUN. 

COBOL Notes

  1. The PROGRAM-ID paragraph identifies the program by specifying the program name, which is the global symbol associated with the entry point. The compiler builds the entry mask.
  2. Enough bytes are allocated for the alphanumeric output data. The compiler generates a descriptor when you specify USING BY DESCRIPTOR in the CALL statement.
  3. The value of the symbolic code LNM$STRING is 2. Section 4.4.5 explains how to obtain values for symbolic codes.
  4. This definition reserves a signed longword with COMP (binary) usage to receive the output value.
  5. The service is called by the SYS$ form of the service name, and the name is enclosed in quotation marks.
    Specify arguments in positional order only, with the USING statement. You cannot omit arguments; if you are accepting the default for an argument, you must pass the default value explicitly (OMITTED in this example).
    You can specify explicitly how each argument is being passed: by descriptor, by reference (that is, by address), or by value. You can also implicitly specify how an argument is being passed: through the default mechanism (by reference), or through association with the last specified mechanism (thus, the last two arguments in the example are implicitly passed by value).
  6. The input string is defined as alphanumeric (ASCII) data. The compiler generates a descriptor when you specify USING BY DESCRIPTOR in the CALL statement.
  7. The IF statement tests RESULT for a failure status. In this case, control is passed to the routine ERROR-CHECK.

Example 4-7 System Service Call in FORTRAN

 SUBROUTINE ORION 
 IMPLICIT NONE                 ! Require declaration of all symbols 
 INCLUDE '($SYSSRVNAM)'        ! Declare system service names  (1)
 INCLUDE '($LNMDEF)'           ! Declare $TRNLNM item codes 
 INCLUDE '(LIB$ROUTINES)'      ! Declare LIB$ routines 
 
 STRUCTURE /ITEM_LIST_3_TYPE/  ! Structure of item list  (2)
   INTEGER*2 BUFLEN            ! Item buffer length 
   INTEGER*2 ITMCOD            ! Item code 
   INTEGER*4 BUFADR            ! Item buffer address 
   INTEGER*4 RETADR            ! Item return length address 
 END STRUCTURE 
 RECORD /ITEM_LIST_3_TYPE/ ITEMLIST(2)  ! Declare itemlist 
 
 CHARACTER*255 EQUIV_NAME      ! For returned equivalence name 
 INTEGER*2 NAMLEN              ! For returned name length 
 VOLATILE EQUIV_NAME,NAMLEN  (3)
 
 INTEGER*4 STATUS              ! For returned service status  (4)
 
 ! Fill in itemlist 
 ! 
 ITEMLIST(1).ITMCOD = LNM$_STRING 
 ITEMLIST(1).BUFLEN = LEN(EQUIV_NAME)  (5)
 ITEMLIST(1).BUFADR = %LOC(EQUIV_NAME) 
 ITEMLIST(1).RETADR = %LOC(NAMLEN) 
 ITEMLIST(2).ITMCOD = 0               ! For terminator 
 ITEMLIST(2).BUFLEN = 0 
 
 ! Call SYS$TRNLM 
 ! 
 STATUS = SYS$TRNLNM (,               ! ATTR omitted  (6)
 1                    'LNM$FILE_DEV', ! TABNAM 
 2                    'CYGNUS',       ! LOGNAM 
 3                    ,               ! ACMODE omitted 
 4                    ITEMLIST)       ! ITMLST 
 
 ! Check return status, display translation if successful 
 ! 
 IF (.NOT. STATUS) THEN   (7)
     CALL LIB$SIGNAL(%VAL(STATUS)) 
 ELSE 
     WRITE (*,*) 'CYGNUS translates to: "', 
 1       EQUIV_NAME(1:NAMLEN), '"' 
 END IF 
 END 

FORTRAN Notes


Previous Next Contents Index

  [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]  
  privacy and legal statement  
5843PRO_006.HTML