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]

Guide to Creating OpenVMS Modular Procedures


Previous Contents Index

2.4.2 Using Event Flags

Event flags allow modular procedures to communicate with each other and to synchronize their operations. Because they can be allocated at run time, event flags allow one procedure to run independently of other procedures existing in the same process.

Event flags are allocated and deallocated by the run-time library procedures LIB$GET_EF and LIB$FREE_EF. (For more information, see the descriptions of the LIB$GET_EF and LIB$FREE_EF procedures in the OpenVMS Programming Concepts Manual and the OpenVMS RTL Library (LIB$) Manual.)

2.4.3 Using Logical Unit Numbers

A logical unit number is used to define the device or file a program uses to perform input and output. Modular procedures do not need to know the unit numbers of other procedures running at the same time.

Logical unit numbers are used only in BASIC and FORTRAN.

Logical unit numbers should be allocated and deallocated using the LIB$GET_LUN and LIB$FREE_LUN RTL procedures. (For more information about using logical unit numbers, see the descriptions of the LIB$GET_LUN and LIB$FREE_LUN procedures in the OpenVMS Programming Concepts Manual and the OpenVMS RTL Library (LIB$) Manual.)

2.5 Using Input/Output

In general, your procedure's input/output (I/O) is directed to either the terminal or a file. (In some cases, you may need to use mailbox I/O and network operations. For information about these areas, see the DECnet for OpenVMS Networking Manual.) Regardless of whether you are directing input/output to the terminal screen or to a file, you must follow two rules to maintain modularity:

  1. A procedure must not print error or informational messages either directly or by calling the $PUTMSG system service. It must either return a condition value in R0 as a function value, or call LIB$SIGNAL or LIB$STOP to output all messages. (LIB$SIGNAL and LIB$STOP can be called either directly or indirectly.)
  2. A procedure should use device-independent services and procedures for input/output.

2.5.1 Terminal Input/Output

The methods available for performing input/output to the terminal include the following:

During I/O to the terminal, it is important that the procedure and the main program cooperate in controlling the terminal screen. For example, an I/O procedure may write something to the terminal screen that the calling program wants to erase. To erase it, the calling program must know both what and where that information is. The calling program and the called procedure must communicate by passing arguments that define which part of the screen will be accessed by each. The run-time library contains Screen Management (SMG$) procedures for this purpose.

Do not combine different methods of I/O within your application. Problems can arise if the calling program and the called procedure use different methods of I/O. Each method of performing input/output maintains some knowledge of what is on the terminal screen. At the very least, the current cursor position is remembered. If another type of I/O is performed, that information is not updated and, therefore, becomes incorrect. The results of any subsequent I/O would be unpredictable. If you must combine other methods with uses of SMG$ procedures, use the SMG$ procedures that aid such an integration.

2.5.2 File Input/Output

File I/O can be performed by the following methods:

2.6 Documenting Modules

You should document every module you create so that you and others know what the procedure does. Each module should include:

In most cases, a module should contain only one procedure.

2.6.1 Writing a Module Preface

At the beginning of every module, include a preface that contains the following information:
Title: Module name followed by a one-line functional description.
Version: Version and a three-digit edit number. Generally 1-001 is the original version.
Facility: Description of the library facility, such as general utility library (LIB).
Abstract: Short (three to six lines) functional description of the module.
Environment: Describe any special environmental assumptions that the module can make. These include assumptions made at both compilation and execution time that could affect either the hardware or software environments.

Describes situations that the module assumes during execution time and optional modular programming elements that your module does not follow.

Indicates the reentrancy characteristics of the procedures in this module. Each procedure is either fully reentrant, AST reentrant, or nonreentrant.

Author: Your name and date the module was created.
Modified by: Modification number, name of modifying programmer, modification date, and a list of the modifications.

End the preface with a page delimiter. After the preface, include the code for the procedure.

Example 2-4 shows a sample module description.

Example 2-4 Sample Module Description

        PROGRAM GRA_CUBE                ! Create representation of a cube 
 
!+ 
! VERSION:      1-002 
! 
! FACILITY:     User Graphics Computation Library 
! 
! ABSTRACT:     This module contains a procedure to create a mathematical 
!               representation of a cube, GRA_CUBE. 
! 
! ENVIRONMENT:  User Mode, AST-reentrant 
! 
! AUTHOR:       John Smith                CREATION DATE:  14-Sep-1993 
! 
! MODIFIED BY: 
! 1-001 - Original.  DWS 14-Sep-1993 
! 1-002 - Fix a minor bug in cube volume computation.  MDL 15-Mar-1993 
!- 
 

2.6.2 Writing a Procedure Description

At the beginning of every procedure in a module, describe the procedure by including the information in this section. Include all the description elements, even if they are not in the procedure. For example, if a procedure has no implicit inputs, write the following:


! 
!  Implicit Inputs: 
! 
!       NONE 
! 

Every procedure description should include the following information:
Functional description: Describes a procedure's purpose and completely documents its interfaces.

Includes the basis for any critical algorithms used, including literature references where applicable, and explains why a particular algorithm was chosen.

Indicates the reentrancy characteristics of this procedure if they differ from those given in the module description.

Calling sequence: Includes these elements in the following order:
  1. A return status, value argument, or CALL statement
  2. The procedure name
  3. The argument list (typically a list of registers or arguments)

In VAX MACRO, each argument is symbolically defined as the offset relative to the argument pointer (AP).

Lists the arguments in the order they will appear in a high-level language. Each argument characteristic should also be included, using the procedure argument notation described in OpenVMS Programming Interfaces: Calling a System Routine.

Formal arguments: Lists any explicit input, input/output, or output arguments. Includes a qualifying description with each argument. The arguments should be listed in the order they are listed in the calling sequence.
Implicit inputs: Lists any inputs from storage, internal or external to the module, that are not specified in the argument list. Usually all that will appear here is NONE. See Section 2.2.2.
Implicit outputs: Lists any outputs to internal or external storage that are not specified in the argument list.
Completion status or
routine value:
Lists the success or failure condition value symbols that could be returned. If your procedure returns a function value other than a condition value, change the heading to "Routine value."
Side effects: Describes any functional side effects not evident from a procedure's calling sequence. This includes changes in storage allocation, process status, file operations, and possible signaled conditions. In general, you should document anything out of the ordinary that the procedure does to the environment. If a side effect modifies local or global storage locations, document it in the implicit output description instead.

Example 2-5 shows a sample procedure description.

Example 2-5 Sample Procedure Description

!++ 
! FUNCTIONAL DESCRIPTION: 
! 
!       Return the system date and time, using the caller's 
!       semantics for his/her string. 
! 
!       Non-reentrant; uses static storage. 
! 
! FORMAL ARGUMENT(S): 
! 
!       RESULT_ADDR 
!       VMS USAGE : char_string 
!       TYPE      : character string 
!       ACCESS    : write only 
!       MECHANISM : by descriptor 
! 
!      Address of the descriptor into which the 
!      system date and time is written. 
! 
! IMPLICIT INPUTS: 
! 
!       NONE 
! 
! IMPLICIT OUTPUTS: 
! 
!       NONE 
! 
! COMPLETION CODES: 
! 
!       SS$_NORMAL      Procedure successfully completed 
!       LIB$_STRTRU     Success, but source string truncated 
! 
! SIDE EFFECTS: 
! 
!       Requests the current date and time from OpenVMS. 
! 
!-- 

2.7 Planning for Signaling and Condition Handling

Two methods are available to a procedure for indicating to its caller whether it completed successfully. One method is to return a condition value. The other method is to signal an error condition.

To provide a better user interface, all procedures in a facility should either return condition values or signal error conditions. Regardless of which method you choose, you should be consistent within the facility to make the procedures easier for the user to call.

2.7.1 Guidelines for Signaling Error Conditions

The signaling of an error condition is, in some instances, mandatory.

Procedures that return a function value cannot also return a condition value and therefore must signal any error conditions encountered.

However, to maintain efficiency, you might want other procedures to signal error conditions also. Checking the return status of a called procedure for repetitive calls can be time consuming and adversely affect the performance of the calling program. For example, if you are going to call a procedure 100 times within a loop and the chances of that procedure's failure are small, you may not want to take the time to check the return status after each call to make sure that the condition value returned was SS$_NORMAL. Signaling error conditions is far more efficient in this type of application.

From the point of view of the calling program, handling a signaled condition is slightly more difficult than checking a returned condition value because it involves writing a condition handler to be invoked in the event that an error condition is signaled. However, handling a signaled condition allows the calling program to execute more efficiently.

To signal an error condition, your procedure uses either a condition-handling mechanism provided by the source language, or it calls the Run-Time Library procedure LIB$SIGNAL. To use LIB$SIGNAL, your procedure calls LIB$SIGNAL and specifies the condition code and zero or more arguments specifying the environment of the condition. For more information about using LIB$SIGNAL, see the OpenVMS RTL Library (LIB$) Manual.

2.7.2 Guidelines for Returning Condition Values

From the point of view of the calling program, it is much easier to check returned condition values than to handle signaled error conditions. When the condition value is being returned, the calling program does not need to include a condition handler. The calling program needs only to check the status of the returned value.

However, if you return condition values rather than signal error conditions, you return less information about the error condition to the calling program. Digital recommends that you return condition values when the explanation of the error condition is simple and self contained. For example, LIB$GET_VM returns a condition value, because the possible status conditions are self contained and simple (for example, insufficient virtual memory).

According to the OpenVMS Calling Standard, the status returned must be a condition value. (For more information, see OpenVMS Programming Interfaces: Calling a System Routine.)

2.7.3 When to Signal or Return Condition Values

To some degree, whether you decide to signal an error condition or return a condition value depends on the language you are using for your procedure. In some high-level languages, it is difficult to write a condition handler to be invoked in the event that an error condition is signaled. (For more information about condition handling in your language, consult the appropriate language reference manual.)

Regardless of which language you are using, there are general guidelines for when to return a condition value and when to signal an error condition.

You should signal an error condition in the following situations:

You should return a condition value in the following situations:


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  
4518PRO_002.HTML