3.7 Calling Routines

The basic steps for calling routines are the same whether you are calling a routine written in DEC C, a routine written in some other OpenVMS language, a system service, or an OpenVMS Run-Time Library (RTL) routine. The following sections outline the procedures for calling non-DEC C routines.

3.7.1 Determining the Type of Call

Before calling an external routine, you must first determine whether the call should be a procedure call or a function call. Call a routine as a procedure if it does not return a value. Call a routine as a function if it returns any type of value.

3.7.2 Declaring an External Routine and Its Arguments

To call an external routine or system routine, you need to declare it as an external function and to declare the names, data types, and passing mechanisms of its arguments. Arguments can be either required or optional.

Include the following information in a routine declaration:

The following example shows how to declare an external routine and its arguments:

char func_name (int x, char y);

3.7.3 Calling the External Routine

After declaring an external routine, you can invoke it. To invoke a function, you must specify the name of the routine being invoked and all arguments required for that routine. Make sure the data types for the actual arguments you are passing coincide with those of the parameters you declared earlier, and with those declared in the routine. The following example shows how to invoke the function declared in Section 3.7.2:

ret_status = func_name(1,'a');

3.7.4 System Routine Arguments

All system routine arguments are described in terms of the following information:

OpenVMS usages are data structures that are layered on the standard OpenVMS data types. For example, the OpenVMS usage mask_longword signifies an unsigned longword integer that is used as a bit mask, and the OpenVMS usage floating_ point represents any OpenVMS floating-point data type. Table 3-12 lists all the OpenVMS usages and the DEC C types you need to implement them.

Table 3-12 DEC C Implementation

OpenVMS Data Type  DEC C Declaration 
access_bit_names  user-defined[1] 
access_mode  unsigned char 
address  int *pointer[2,4] 
address_ range  int *array [2] [2,3,4] 
arg_list  user-defined[1] 
ast_procedure  pointer to a function[2] 
boolean  unsigned long int 
byte_signed  char 
byte_unsigned  unsigned char 
channel  unsigned short int 
char_string  char array[n][3,5] 
complex_number  user-defined[1] 
cond_value  unsigned long int 
context  unsigned long int 
date_time  user- defined[1] 
device_name  char array[n][3,5] 
ef_cluster_ name  char array[n][3,5] 
ef_ number  unsigned long int 
exit_handler_block  user-defined[1] 
fab  #include fab from text library struct FAB 
file_protection  unsigned short int, or user-defined[1] 
floating_point  float or double 
function_code  unsigned long int or user-defined[1] 
identifier  int *pointer[2,4] 
io_status_ block  user-defined[1] 
item_ list_2  user-defined[1] 
item_list_3  user-defined[1] 
item_list_pair  user-defined[1] 
item_quota_list  user-defined[1] 
lock_id  unsigned long int 
lock_status_block  user- defined[1] 
lock_value_block  user-defined[1] 
logical_ name  char array[n][3,5] 
longword_signed  long int 
longword_unsigned  unsigned long int 
mask_byte  unsigned char 
mask_longword  unsigned long int 
mask_quadword  user- defined[1] 
mask_word  unsigned short int 
null_arg  unsigned long int 
octaword_ signed  user-defined[1] 
octaword_unsigned  user-defined[1] 
page_protection  unsigned long int 
procedure  pointer to function[2] 
process_id  unsigned long int 
process_ name  char array[n][3,5] 
quadword_signed  user-defined[1] 
quadword_unsigned  user- defined[1] 
rights_holder  user-defined[1] 
rights_id  unsigned long int 
rab  #include rab struct RAB 
section_id  user- defined[1] 
section_name  char array[n][3,5] 
system_access_ id  user-defined[1] 
time_ name  char array[n][3,5] 
uic  unsigned long int 
user_arg  user-defined[1] 
varying_arg  user-defined[1] 
vector_byte_signed  char array[n][3,5] 
vector_byte_unsigned  unsigned char array[n][3,5] 
vector_longword_ signed  long int array[n][3,5] 
vector_longword_unsigned  unsigned long int array[n][3,5] 
vector_ quadword_signed  user-defined[1] 
vector_quadword_unsigned  user- defined[1] 
vector_word_signed  short int array[n][3,5] 
vector_word_ unsigned  unsigned short int array[n][3,5] 
word_signed  short int 
word_unsigned  unsigned short int 

[1] The declaration of a user-defined data structure depends on how the data will be used. Such data structures can be declared in a variety of ways, each of which is more suitable to specific applications.

[2] The term pointer refers to several declarations involving pointers. Pointers are declared with special syntax and are associated with the data type of the object being pointed to. This object is often user-defined.

[3] The term array denotes the syntax of a DEC C array declaration.

[4] The data type specified can be changed to any valid DEC C data type.

[5] The size of the array must be substituted for n.

If a system routine argument is optional, it will be indicated in the format section of the routine description in one of two ways, as follows:

If the comma appears outside the brackets, you must pass a 0 by value to indicate the place of the omitted argument. If the comma appears inside the brackets, you can omit the argument if it is the last argument in the list.

3.7.5 Symbol Definitions

Many system routines depend on values that are defined in separate symbol definition files. OpenVMS RTL routines require you to include symbol definitions when you are calling a Screen Management facility routine or a routine that is a jacket to a system service. A jacket routine provides an interface to the corresponding system service. For example, the routine LIB$SYS_ASCTIM is a jacket routine for the $ASCTIM system service.

If you are calling a system service, you must include the <ssdef.h> header file to check the status. Many system services require other symbol definitions as well. To determine whether you need to include other symbol definitions for the system service you want to use, see the documentation for that particular system service. If the documentation states that values are defined in a macro, you must include those symbol definitions in your program.

For example, the description for the flags parameter in the SYS$MGBLSC (Map Global Section) system service states that "Symbolic names for the flag bits are defined by the $SECDEF macro." Therefore, when you call SYS$MGBLSC you must include the definitions provided in the $SECDEF macro by including the <secdef.h> header file.

In DEC C, a header file is included as follows:

#include <ssdef.h>

To obtain a list of all DEC C header files, see Section 1.3.1.2.

3.7.6 Condition Values

Many system routines return a condition value that indicates success or failure; this value can be either returned or signaled. If a condition value is returned, then you must check the returned value to determine whether the call to the system routine was successful. Otherwise, the condition value is signaled to your program instead of being written to a storage location.

Condition values indicating success appear first in the list of condition values for a particular routine, and success codes have odd values. A success code that is common to many system routines is the condition value SS$_NORMAL, which indicates that the routine completed normally and successfully. If the condition value is returned, then you can test for SS$_NORMAL as follows:

      if (ret_status != SS$_NORMAL)
             LIB$STOP();

Because all success codes have odd values, you can check a return status for any success code. For example, you can cause execution to continue only if a success code is returned by including the following statements in your program:

if ((ret_status & 1) != 0)
     LIB$STOP (ret_status);

In general, you can check a return status for a particular success or failure code or you can test the condition value returned against all success codes or all failure codes.

3.7.7 Checking System Service Return Values

It is customary in OpenVMS programming to compare the return status of a system service with a global symbol, not with the literal value associated with a particular return status. Consequently, a high-level language program should define the possible return status values for a service as symbolic constants. In DEC C, you can do this by including the <ssdef.h> header file; Example 3-19 shows how this is done.

Example 3-19 Checking System Service Return Values

/*  This program shows how to compare the status of a system   *
 *  service with a global symbol.                              */

                                   /*  Define system service   *
                                    *   status values          */
#include <ssdef.h>
#include <stdio.h>

                                   /*  Declaration of the      *
                                    *   service (not required) */
int  SYS$SETEF();

int main(void)
{
                                   /*  To hold the status of   *
                                    *   SYS$SETEF              */
   int  efstatus;
                                   /*  Argument values for     *
                                    *   SYS$SETEF              */
   enum  cluster0
      {
         completion, breakdown, beginning
      }  event;
      .
      .
      .
   event =  completion;

                                   /*  Set the event flag      */
   efstatus =  SYS$SETEF(event);

                                   /*  Test the return status  */
   if (efstatus == SS$_WASSET)
      fprintf (stderr,"Flag was already set\n");
   else
      if (efstatus == SS$_WASCLR)
         fprintf(stderr, "Flag was previously clear\n");
      else
         fprintf(stderr,
                 "Could not set completion event flag.\n \
Possible programming error.\n");

   exit(efstatus);
}

The system service return status values (SS$_WASSET and SS$_WASCLR) in Example 3-19 are defined by the <ssdef.h> header file.

Error handling in Example 3-19 is typical of programs running on OpenVMS systems. Using the following statements, the example program attempts to provide a program-specific error message and then passes the offending error status to the caller:

else
   fprintf(stderr,
           "Could not set completion event flag.\n \
Possible programming error.\n");

exit(efstatus);

If you execute the program with DCL, it interprets any status value the program returns. DCL prints a standard error message on the terminal to provide you with more information about the failure. For example, if the program encounters the SS$_ILLEFC return status, DCL displays the following messages:

Could not set completion event flag.
Possible programming error.
%SYSTEM-F-ILLEFC, illegal event flag cluster.


Previous Page | Next Page | Table of Contents | Index