[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.9.1 Format of Return Status Values

All OpenVMS system procedures and programs use a longword value to communicate return status information. When a HP C main function executing under the control of the DCL interpreter executes a return statement to return control to the command level, the command interpreter uses the return status value to conditionally display a message on the current output device.

To provide a unique means of identifying every return condition in the system, bit fields within the value are defined as shown in Figure 3-5.

Figure 3-5 Bit Fields Within a Return Status Value


The following list describes the division of this bit field:

control bits (31-28)

Define special action(s) to be taken. At present, only bit 28 is used. When set, it inhibits the printing of the message associated with the return status value at image exit. Bits 29 through 31 are reserved for future use by HP and must be 0.

facility number (27-16)

A unique value assigned to the system component, or facility, that is returning the status value. Within this field, bit 27 has a special significance. If bit 27 is clear, the facility is a HP facility: the remaining value in the facility number field is a number assigned by the operating system. If bit 27 is set, the number indicates a customer-defined facility.

message number (15-3)

An identification number that specifically describes the return status or condition. Within this field, bit 15 has a special significance. If bit 15 is set, the message number is unique to the facility issuing the message. If bit 15 is clear, the message is issued by more than one system facility.

severity (2-0)

A numeric value indicating the severity of the return status. Table 3-13 shows the possible values in these three bits, and their meanings.

Table 3-13 Possible Severity Values
Value Meaning
0 Warning
1 Success
2 Error
3 Informational
4 Severe error, FATAL
5-7 Reserved

Odd values indicate success (an informational condition is considered a successful status) and even values indicate failures (a warning is considered an unsuccessful status).

The following names are associated with these fields:

control bits
bit 28 (inhibit message)
CONTROLINHIB_MSG
facility number
bit 27 (customer facility)
FAC_NOCUST_DEF
message number
bit 15 (facility specific)
MSG_NOFAC_SP
severity
bit 0 (success)
SEVERITYSUCCESS

When testing return values in a HP C program, either you can test only for successful completion of a procedure or you can test for specific return status values.

3.9.2 Manipulating Return Status Values

You can construct a structure or union that describes a return status value, but this method of manipulating return status values is not recommended. A status value is usually constructed or checked using bitwise operators. HP C provides the <stsdef.h> header file, which contains preprocessor definitions to make this job easier. All the preprocessor symbols are named according to the following OpenVMS naming convention:


STS$type_name

STS

Identifies standard return status values.

type

One of the following characters denoting the type of the constant:
K Represents a constant value
M Represents a bit mask
S Represents the bit size of a field
V Defines the bit offset to the field

name

An abbreviation for the field name.

For example, the following constants are defined in <stsdef.h> for the facility number field, FAC_NO, which spans bits 16 through 27:


                                   /*  Size of field in bits   */ 
#define STS$S_FAC_NO  12 
 
                                   /*  Bit offset to the       * 
                                    *   beginning of the field */ 
#define STS$V_FAC_NO   16 
 
                                   /*  Bit mask of the field   */ 
#define STS$M_FAC_NO   0xFFF0000 

Figure 3-6 shows how the status value is represented internally.

Figure 3-6 Internal Representation of a Status Value


Use the following expression to extract the facility number from a particular status value contained in the variable named status:


(status & STS$M_FAC_NO) >> STS$V_FAC_NO 

In the previous example, the parentheses are required for the expression to be evaluated properly; the relative precedence of the bitwise AND operator (&) is lower than the precedence of the binary shift operator (>>).

3.9.3 Testing for Success or Failure

To test a return status value for success or failure, you need only test the success bit. A value of true in this bit indicates that the return value is a successful value.

Example 3-21 shows a program that checks the success bit.

Example 3-21 Testing for Success

/*  This program shows how to test the success bit.            */ 
 
#include <stdio.h> 
#include <descrip.h> 
#include <stsdef.h> 
#include <starlet.h> 
#include <stdlib.h> 
 
int main(void) 
{ 
   int  status; 
   $DESCRIPTOR(name, "student"); 
 
   status = sys$setprn(&name); 
 
   if (status & STS$M_SUCCESS) 
                                   /*  Success code            */ 
        fprintf(stderr, "Successful completion"); 
 
   else 
                                   /*  Failure code            */ 
      fprintf(stderr, "Failed to set process name.\n"); 
   exit(status); 
} 

The failure code in Example 3-21 causes the printing of a program-specific message indicating the condition that caused the program to terminate. The error status is passed to the DCL by the exit function, which then interprets the status value.

3.9.4 Testing for Specific Return Status Values

Each numeric return status value defined by the system has a symbolic name associated with it. The names of these values are defined as system global symbols, and you can access their values by referring to their symbolic names.

The global symbol names for OpenVMS return status values have the following format:


facility$_code

facility

An abbreviation or acronym for the system facility that defined the global symbol.

code

A mnemonic for the specific status value.

Table 3-14 shows some examples of facility codes used in global symbol names.

Table 3-14 Facility Codes
Facility Description
SS System services; these status codes are listed in the HP OpenVMS System Services Reference Manual.
RMS File system procedures; these status codes are listed in the OpenVMS Record Management Services Reference Manual.
SOR SORT procedures; these status codes are listed in the VMS Sort/Merge Utility Manual.

The definitions of the global symbol names for the facilities listed are located in the default HP C object module libraries, so they are automatically located when you link a HP C program that references them.

When you write a HP C program that calls system procedures and you want to test for specific return status values using the symbol names, you must perform the following tasks:

  1. Determine, from the documentation of the procedure, the status values that can be returned, and choose the values for which you want to provide specific tests.
  2. Declare the symbolic name for each value of interest. The <ssdef.h> and <rmsdef.h> header files define the system service and RMS return status values, respectively. If you are checking return status values from other facilities, such as the SORT utility, you must explicitly declare the return values as globalvalue int . Consider the following example:


    globalvalue  int  SOR$_OPENIN; 
    
  3. Reference the symbols in your program.

Example 3-22 shows a program that checks for specific return status values defined in the <ssdef.h> header file.

Example 3-22 Testing for Specific Return Status Values

/*  This program checks for specific return status values.     */ 
 
 
#include <stdlib.h> 
 
#include <ssdef.h> 
#include <stdio.h> 
#include <descrip.h> 
 
$DESCRIPTOR(message,"\07**Lunch_time**\07"); 
 
int main(void) 
{ 
 
   int status =  SYS$BRDCST(&message,0); 
 
   if (status != SS$_NORMAL) 
      { 
         if (status == SS$_NOPRIV) 
            fprintf(stderr, "Can't broadcast; requires OPER \
privilege."); 
 
         else 
            fprintf(stderr, "Can't broadcast; some fatal \
error."); 
 
         exit(status); 
      } 
} 

3.10 Examples of Calling System Routines

This section provides complete examples of calling system routines from HP C. Example 3-23 shows the three mechanisms for passing arguments to system services and also shows how to test for status return codes. Example 3-24 shows various ways of testing for successful $QIO completion. Example 3-25 shows how to use time conversion and set timer routines.

In addition to the examples provided here, the VMS Run-Time Library Routines Volume and the HP OpenVMS System Services Reference Manual also provide examples for selected routines. See these manuals for help on using a specific system routine.

Example 3-23 Passing Arguments to System Services

/* GETMSG.C 
   This program is an example showing the three mechanisms 
   for passing arguments to system services.  It also 
   shows how to test for specific status return 
   codes from a system service call. */ 
 
#include <stdio.h> 
#include <descrip.h> 
#include <ssdef.h> 
#include <lib$routines.h> 
 
int main(void) 
{ 
int message_id; 
short message_len; 
char text[133]; 
$DESCRIPTOR(message_text, text); 
register status; 
 
while (printf("\nEnter a message number <Ctrl/Z to quit>: "), 
       scanf("%d", &message_id) != EOF) 
   { 
   /* Retrieve message associated with the number. */ 
   status = SYS$GETMSG(message_id, &message_len, 
                       &message_text, 15, 0); 
 
   /* Check for status conditions. */ 
   if (status == SS$_NORMAL) 
      printf("\n%.*s\n", message_len, text); 
   else if (status == SS$_BUFFEROVF) 
      printf("\nBUFFER OVERFLOW -- Text is: %.*s\n", 
              message_len, text); 
   else if (status == SS$_MSGNOTFND) 
      printf("\nMESSAGE NOT FOUND.\n"); 
   else 
      { 
      printf("\nUnexpected error in $GETMSG call.\n"); 
      LIB$STOP(status); 
      } 
   } 
} 

Example 3-24 Determining$QIO Completion

/* ASYNCH.C 
   This program shows various ways to determine 
   $QIO completion. It also shows the use of an 
   IOSB to obtain information about the I/O operation. */ 
 
#include <iodef.h> 
#include <ssdef.h> 
#include <descrip.h> 
#include <lib$routines.h> 
#include <stdio.h> 
#include <starlet.h> 
#include <string.h> 
 
typedef struct 
          { 
          short cond_value; 
          short count; 
          int info; 
          } io_statblk; 
 
main(void) 
{ 
char text_string[]  =  "This was written by the $QIO."; 
register status; 
short chan; 
io_statblk status_block; 
int AST_PROC(); 
$DESCRIPTOR (terminal, "SYS$COMMAND"); 
 
/*  Assign I/O channel.  */ 
if (((status = SYS$ASSIGN (&terminal, &chan,0,0)) & 1) != 1) 
   LIB$STOP (status); 
 
/*  Queue the I/O.  */ 
if (((status = SYS$QIO (1, chan, IO$_WRITEVBLK, &status_block, 
          AST_PROC, &status_block, text_string, 
          strlen(text_string),0,32,0,0)) & 1) != 1) 
   LIB$STOP (status); 
 
/*  Wait for the I/O operation to complete.  */ 
if (((status = SYS$SYNCH (1, &status_block)) & 1) != 1) 
   LIB$STOP (status); 
if ((status_block.cond_value &1) != 1) 
   LIB$STOP(status_block.cond_value); 
 
printf ("\nThe I/O operation and AST procedure are done."); 
} 
 
 
AST_PROC (*write_status) 
io_statblk *write_status; 
 
 
/* This function is called as an AST procedure. It uses 
   the AST parameter passed to it by $QIO to determine 
   how many characters were written to the terminal. */ 
 
{ 
printf("\nNumber of characters output is  %d", write_status->count); 
printf("\nI/O completion status is %d", write_status->cond_value); 
} 

Example 3-25 Using Time Routines

/*  ALARM.C 
    This program shows the use of time conversion 
    and set timer routines.  */ 
 
#include <stdio.h> 
#include <descrip.h> 
#include <ssdef.h> 
 
#include <lib$routines.h> 
#include <starlet.h> 
 
 
main(void) 
{ 
#define event_flag 2 
#define timer_id 3 
 
typedef int quadword[2]; 
 
quadword delay_int; 
$DESCRIPTOR(offset, "0 ::15.00"); 
char cur_time[24]; 
$DESCRIPTOR(cur_time_desc, cur_time); 
int i; 
unsigned state; 
register status; 
 
/* Convert offset from ASCII to binary format. */ 
if (((status=SYS$BINTIM(&offset, delay_int)) &1) != 1) 
   LIB$STOP(status); 
 
/* Output current time. */ 
if (((status=LIB$DATE_TIME(&cur_time_desc)) &1) != 1) 
   LIB$STOP(status); 
cur_time[23] = '\0'; 
printf("The current time is : %s\n", cur_time); 
 
/* Set the timer to expire in 15 seconds. */ 
if (((status=SYS$SETIMR(event_flag, &delay_int, 
                        0, timer_id)) &1) != 1) 
   LIB$STOP(status); 
 
/* Count to 1000000. */ 
printf("beginning count....\n"); 
for (i=0; i<=1000000; i++) 
   ; 
 
/* Check if the timer expired. */ 
switch (status = SYS$READEF(event_flag, &state)) 
 { 
 case SS$_WASCLR : /* Cancel timer */ 
                   if (((status=SYS$CANTIM(timer_id, 0)) &1) != 1) 
                       LIB$STOP(status); 
                   printf("Count completed before timer expired.\n"); 
                   printf("Timer canceled.\n"); 
                   break; 
 case SS$_WASSET : printf("Timer expired before count completed.\n"); 
                   break; 
 default         : LIB$STOP(status); 
                   break; 
 } 
} 


Chapter 4
Data Storage and Representation

This chapter presents the following topics concerning HP C data storage and representation on OpenVMS systems:

4.1 Storage Allocation

When you define a HP C variable, the storage class determines not only its scope but also its location and lifetime. The lifetime of a variable is the length of time for which storage is allocated. For OpenVMS systems, storage for a HP C variable can be allocated in the following locations:

  • On the run-time stack
  • In a machine register
  • In a program section (psect)

Variables that are placed on the stack or in a register are temporary. For example, variables of the auto and register storage classes are temporary. Their lifetimes are limited to the execution of a single block or function. All declarations of the internal storage classes ( auto and register ) are also definitions; the compiler generates code to establish storage at this point in the program.

Program sections, or psects, are used for permanent variables; the lifetime of identifiers extends through the course of the entire program. A psect represents an area of virtual memory that has a name, a size, and a series of attributes that describe the intended or permitted usage of that portion of memory. For example, the compiler places variables of the static, external, and global storage classes in psects; you have some control as to which psects contain which identifiers. All declarations of the static storage class are also definitions; the compiler creates the psect at that point in the program. In HP C, the first declaration of the external storage class is also a definition; the linker initializes the psect at that point in the program.

Note

The compiler does not necessarily allocate distinct variables to memory locations according to the order of appearance in the source code. Furthermore, the order of allocation can change as a result of seemingly unrelated changes to the source code, command-line options, or from one version of the compiler to the next; it is essentially unpredictable. The only way to control the placement of variables relative to each other is to make them members of the same struct type or, on OpenVMS Alpha and I64 systems, by using the noreorder attribute on a named #pragma extern_model strict_refdef .

Table 4-1 shows the location and lifetime of a variable when you use each of the storage-class keywords.

Table 4-1 Location, Lifetime, and the Storage-Class Keywords
Storage Class Location Lifetime
(Internal null) Stack or register Temporary
[auto] Stack or register Temporary
register Stack or register Temporary
static Psect Permanent
extern Psect Permanent
globaldef 1 Psect Permanent
globalref 1 Psect Permanent
globalvalue 1 No storage allocated Permanent

1The globaldef, globalref, and globalvalue storage-class specifiers are available only when compiling in VAX C compatibility mode.

For a comparison between the global and external storage classes, see Section 4.3.2.

For more information about psects, see Section 4.8.

4.2 Standard-Conforming Method of Controlling External Objects

Sections 4.3 and 4.4 describe the following external linkage storage-class specifiers and modifiers that are specific to HP C for OpenVMS Systems:

globaldef
globalref
globalvalue
noshare
readonly
_align

These keywords are supported by the HP C compiler for compatibility purposes, and are available only in VAX C mode (/STANDARD=VAXC) and relaxed mode (/STANDARD=RELAXED).

However, the HP C compiler also provides an alternative, standard-conforming method of controlling objects that have external linkage. To take advantage of this method, use the #pragma extern_model preprocessor directive and the /EXTERN_MODEL and /[NO]SHARE_GLOBALS command-line qualifiers.

The pragma and command-line qualifiers replace the VAX C mode storage-class specifiers ( globaldef , globalref , globalvalue ) and storage-class modifiers ( noshare and readonly ). They allow you to select the implementation model of external data and control the psect usage of your programs. The _align storage-class modifier is still used to ensure object alignment.

The pragma and command-line qualifier approach also has these advantages:

  • Since the VAX C mode keywords do not follow standard C spelling rules, they cannot be provided in strict ANSI C mode. The pragma and qualifiers, however, can be used in any mode of the HP C compiler.
  • The pragma and qualifiers allow extern on OpenVMS systems to function in a manner more similar to other systems.
  • The pragma and qualifiers make it easier for you to write OpenVMS shareable images with HP C. Previously, that task required you to add an additional keyword to every declaration of external data.

For a description of the #pragma extern_model preprocessor directive and its relationship to the external storage classes it replaces, see Section 5.4.5.

For a description of the _align storage-class modifier, see Section 4.4.3.

For a description of the /EXTERN_MODEL and /[NO]SHARE_GLOBALS command-line qualifiers, see Section 1.3.4.


Previous Next Contents Index