[an error occurred while processing this directive]

HP OpenVMS Systems

C Programming Language
Content starts here HP C

HP C
User's Guide for OpenVMS Systems


Previous Contents Index

3.7 Calling Routines

The basic steps for calling routines are the same whether you are calling a routine written in HP 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-HP 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 name of the external routine
  • The data types of all the routine parameters (optional)
  • The data type of the return value if it is a function
  • The void keyword if it is a procedure

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


char func_name (int x, char y); 

Header files are available to declare commonly used external routines. Using them will save you a lot of work. See Sections 1.3.1.1 and 1.3.1.2 in this manual for information on listing and including header files.

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 usage
  • Data type
  • Type of access allowed
  • Passing mechanism

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 HP C types you need to implement them.

Table 3-12 HP C Implementation
OpenVMS Data Type HP 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

1The 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.
2The 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.
3The term array denotes the syntax of a HP C array declaration.
4The data type specified can be changed to any valid HP C data type.
5The 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:

  • [,optional-argument]
  • ,[optional-argument]

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.

For more information, see the OpenVMS Programming Interfaces: Calling a System Routine manual. This manual describes the OpenVMS programming interface and defines the standard conventions to call an OpenVMS system routine from a user procedure. The Alpha and VAX data type implementations for various high-level languages are also presented.

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 HP C, a header file is included as follows:


#include <ssdef.h> 

To obtain a list of all HP 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 HP 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.                              */ 
 
#include <stdlib.h> 
 
                                   /*  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. 

3.8 Variable-Length Argument Lists in System Services

Most system services and other external procedures require a specific number of arguments, but some accept a variable number of optional arguments. Because HP C function declarations do not show the number of parameters expected by external functions unless a function prototype is used, the way you call an external function from a HP C program depends on the semantics of the called function. You must supply the number of arguments that the external function expects. The rules are as follows:

  • When optional arguments occur between required arguments, they cannot be omitted. If omitting such an argument is necessary---for example, to select a default action---the argument must be written as a zero.
  • When optional arguments occur at the end of an argument list, the format of the function reference depends on the action of the called function as follows:
    • If the called function checks the number of arguments passed, you can omit optional trailing arguments from the function reference. System services generally do not check the length of the argument list.
    • If the called function does not check the number of arguments passed, all arguments must be present in the function reference.

For example, the function STR$CONCAT, in the Common Run-Time Library, concatenates from 2 to 254 strings into a single string. It has the following call format:


ret = STR$CONCAT(dst, src1, src2[, src3,...src254]);

For more information about the STR$CONCAT function, see the VMS Run-Time Library Routines Volume.

The identifier dst is the destination for the concatenated string, and src1, src2, ...src254 are the source strings. All arguments are passed by descriptor. All but the first two source strings are optional. The function checks to see how many arguments are present in the call; if fewer than three (the destination and two sources) are present, the function returns an error status value. Example 3-20 shows a call to the STR$CONCAT function from HP C.

Example 3-20 Using Variable-Length Argument Lists

/*  This example shows a call to STR$CONCAT.                   */ 
 
#include <stdlib.h> 
 
#include <stdio.h> 
#include <descrip.h> 
#include <ssdef.h> 
 
int STR$CONCAT(); 
 
int main(void) 
{ 
   int ret;                        /*  Return status of        * 
                                    *   STR$CONCAT             */ 
 
                                   /*  Destination array of    * 
                                    *   concatenated strings   */ 
   char dest[21]; 
 
                                   /*  Create compile-time     * 
                                    *   descriptors:           */ 
          $DESCRIPTOR(dst, dest); 
   static $DESCRIPTOR(src1, "abcdefghij"); 
   static $DESCRIPTOR(src2, "klmnopqrst"); 
 
                                   /*  Concatenate strings     */ 
   ret =  STR$CONCAT(&dst, &src1, &src2); 
 
                                   /* Test return status value */ 
   if (ret != SS$_NORMAL) 
      fprintf(stderr,"Failed to concatenate strings.\n"), 
      exit(ret); 
 
                                   /*  Process string          */ 
   else 
        dest[20] = '\0', 
        printf("Resultant string: %s\n",dest); 
} 

3.9 Return Status Values

The status values from OpenVMS system service procedures are returned in general register R0. This return status value indicates the success or failure of the operation performed by the called procedure. In HP C, passing a return status value in R0 is equivalent to a function returning int .

To obtain a return status value from any system procedure, declare the procedure as a function, as shown in the following example:


int  SYS$SETEF(); 

After declaring a procedure in this way, you can invoke the procedure as a function and obtain a return status value. In HP C, such a declaration is needed only as program documentation; SYS$SETEF can be called without explicit declaration and will be interpreted by default as a function returning int .

This section describes the following topics:

  • The format of a return status value, that is, the meaning of particular bits within the value
  • The way to manipulate return status values
  • The recommended techniques for testing a return status value for success or failure or for a specific condition


Previous Next Contents Index