|
|
HP C
|
Previous | Contents | Index |
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.
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.
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); |
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.
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'); |
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 HP C types you need to implement them.
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.
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.
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.
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.
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. |
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:
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); } |
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:
Previous | Next | Contents | Index |
|