[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.3.4 Calling HP Pascal

Like HP FORTRAN and HP BASIC, there are certain considerations that you must take into account when calling HP Pascal from HP C and vice versa. When calling HP Pascal from HP C, HP Pascal expects all parameters to be passed by reference. In HP Pascal, there are two different types of semantics: value and variable. The value semantics in HP Pascal are different from passing by value in HP C. Because they are different, you must specify the address of the C parameter.

HP Pascal also expects all strings to be passed by descriptor. If you use the CLASS_S descriptor, the string is passed by using HP Pascal semantics. If the content of the string is changed, it is not reflected back to the caller.

Example 3-12 is an example of how to call a HP Pascal routine from HP C.

Example 3-12 HP C Function Calling a HP Pascal Routine

/* 
 * Beginning of HP C function: 
 */ 
 
#include <descrip.h> 
 
/* This program demonstrates how to call a Pascal routine 
   from a C function. */ 
 
/* A Pascal routine called by a C function. */ 
extern        void        Pascal_Routine (); 
 
main() 
{ 
    struct dsc$descriptor_s to_Pascal_by_desc; 
    char *Message = "The_Max_Num"; 
    int to_Pascal_by_value = 100, 
    to_Pascal_by_ref = 50; 
 
    /* Construct the descriptor. */ 
    to_Pascal_by_desc.dsc$a_pointer = Message; 
    to_Pascal_by_desc.dsc$w_length = strlen (Message); 
    to_Pascal_by_desc.dsc$b_class = DSC$K_CLASS_S; 
    to_Pascal_by_desc.dsc$b_dtype = DSC$K_DTYPE_T; 
 
    /* Pascal expects a calling routine to pass parameters by reference. */ 
 
    Pascal_Routine(&to_Pascal_by_value, &to_Pascal_by_ref, &to_Pascal_by_desc); 
 
    printf ("\nWhen returned from Pascal:\nto_Pascal_by_value is still \
%d\nBut to_Pascal_by_ref is %d\nand Message is still %s\n", 
            to_Pascal_by_value, to_Pascal_by_ref, 
            to_Pascal_by_desc.dsc$a_pointer); 
}  /*  End of HP C function   */ 
{ 
  Beginning of Pascal routine 
} 
 
MODULE C_PASCAL(OUTPUT); 
 
 { This Pascal routine calls the Pascal MAX function 
   to determine the maximum value between 
   'from_c_by_value` and 'from_c_by_ref`, and then 
   assigns the result back to 'from_c_by_ref`. 
   It also tries to demonstrate the results of passing 
   a by-descriptor mechanism. 
   It is called from a C main function.  
 } 
[GLOBAL]PROCEDURE Pascal_Routine 
      (          from_c_by_value :INTEGER; 
      VAR from_c_by_ref :INTEGER; 
          from_c_by_desc :[ CLASS_S ] PACKED ARRAY [l1..u1:INTEGER] OF CHAR 
      ); 
 
    VAR 
        today_is : PACKED ARRAY [1..11] OF CHAR; 
 
    BEGIN 
 
    { Display the contents of formal parameters. } 
    WRITELN; 
    WRITELN ('Parameters passed from C function: '); 
    WRITELN ('from_c_by_value: ', from_c_by_value:4); 
    WRITELN ('from_c_by_ref: ', from_c_by_ref:4); 
    WRITELN ('from_c_by_desc: ', from_c_by_desc); 
 
    { Assign the maximum value into 'from_c_by_ref` } 
    from_c_by_ref := MAX (from_c_by_value, from_c_by_ref); 
 
    { Change the content of 'from_Pascal_by_value` -- 
      to show that the value did not get 
      reflected back to the caller. 
     } 
    from_c_by_value := 20; 
 
    { Put the results of DATE into 'from_c_by_desc` 
      to show that the CLASS_S is only valid with 
      comformant strings passed by value. 
     } 
    DATE (today_is); 
    from_c_by_desc := today_is; 
    WRITELN ('***********************'); 
    WRITELN ('from_c_by_desc is changed to today''s date: "', 
                      from_c_by_desc, '"'); 
    WRITELN ('BUT, this will not reflect back to the caller.'); 
END; 
END. 
{ 
  End of Pascal routine 
} 

Example 3-12 produces the following output:


from_c_by_value:  100 
from_c_by_ref:   50 
from_c_by_desc: The_Max_Num 
*********************** 
from_c_by_desc is changed to today's date "26-MAY-1992" 
BUT, this will not reflect back to the caller. 
 
When returned from Pascal: 
to_Pascal_by_value is still 100 
to_Pascal_by_ref is  100 
and Message is still The_Max_Num 

There are also some considerations when calling HP C from HP Pascal. For example, you can use mechanism specifiers such as %IMMED, %REF, and %STDESCR in HP Pascal. When you use the %IMMED mechanism specifier, the compiler passes a copy of a value rather than an address. When you use the %REF mechanism specifier, the address of the actual parameter is passed to the called routine, which is then allowed to change the value of the corresponding actual parameter. When you use the %STDESCR mechanism specifier, the compiler generates a fixed-length descriptor of a character-string variable and passes its address to the called routine. For more information on these mechanism specifiers and others, see the HP Pascal documentation.

Another consideration is that HP Pascal does not null-pad strings. Therefore, you must add a null character to make the string a C string. Also, when passing a string from HP Pascal to HP C, you can declare a structure declaration in HP C that corresponds to the HP Pascal VARYING TYPE declaration.

Example 3-13 shows an example of how to call HP C from HP Pascal.

Example 3-13 HP Pascal Program Calling a HP C Function

{ 
  Beginning of Pascal function: 
} 
 
PROGRAM PASCAL_C (OUTPUT); 
 
CONST 
        STRING_LENGTH = 80; 
 
TYPE 
        STRING = VARYING [STRING_LENGTH] OF CHAR; 
 
VAR 
    by_value : INTEGER; 
    by_ref : STRING; 
    by_desc: PACKED ARRAY [1..10] OF CHAR; 
 
         
[EXTERNAL] 
PROCEDURE DECC$CRTL_INIT; EXTERN; 
 
[EXTERNAL] 
PROCEDURE c_function 
 (   %immed      by_value :  INTEGER; 
     %ref        by_ref :    STRING ; 
     %stdescr    by_desc:    PACKED ARRAY [l1..u1:INTEGER] OF CHAR 
 );  EXTERN; 
 
BEGIN 
 
    { Establish the appropriate HP C RTL environment for 
       calling the HP C RTL from Pascal. 
    } 
    DECC$CRTL_INIT; 
 
    by_value := 1; 
 
    {                NOTE 
       Pascal does not null pad a string. 
       Therefore, the LENGTH built-in function counts 
       the null pad character while the HP C library function strlen 
       does not include the terminating null character. 
     } 
 
    by_ref := 'TO_C_BY_REF'(0)''; 
    by_desc := 'TERM'(0)''; 
 
    { Call a C function by passing parameters 
       using foreign semantics. 
    } 
    c_function (by_value, by_ref, by_desc); 
 
    WRITELN; 
    WRITELN; 
    WRITELN ('*************************'); 
    WRITELN ('After calling C_FUNCTION: '); 
    WRITELN; 
    WRITELN ('by_value is still ',by_value:3); 
    WRITELN ('however, by_ref contains ',by_ref, 
                     ' (aka Your Terminal Type)'); 
    WRITELN ('and, by_desc still contains ',by_desc); 
            
END. 
{ 
  End of Pascal program 
} 
 
/* 
 *  Beginning of HP C function: 
 * 
 * 
 * A C function called from the Pascal routine. 
 * The parameters are passed to a C function 
 * by value, by reference, and by descriptor, 
 * respectively. 
 */ 
#include <descrip.h> 
 
/* A Pascal style of VARYING data type. */ 
struct Pascal_VARYING 
{ 
    unsigned short        length; 
    char                string[80]; 
}; 
 
 
 
/* This C function calls the HP C RTL function getenv() and puts 
 * your terminal type in 'from_Pascal_by_ref`. 
 * It is called from a Pascal program.  
 */ 
void        c_function  (unsigned char            from_Pascal_by_value, 
                    struct Pascal_VARYING   *from_Pascal_by_ref, 
                    struct dsc$descriptor_s *from_Pascal_by_desc 
                    ) 
{ 
    char *term; 
 
 
 
    /* Display the contents of formal parameters. */ 
    printf ("\nParameters passed from Pascal:\n"); 
    printf ("from_Pascal_by_value: %d\nfrom_Pascal_by_ref: %s\n\
from_Pascal_by_desc: %s\n", from_Pascal_by_value, 
                              from_Pascal_by_ref -> string, 
                              from_Pascal_by_desc -> dsc$a_pointer); 
 
    if ((term = getenv(from_Pascal_by_desc -> dsc$a_pointer)) != 0) 
    { 
          /* Fill 'from_Pascal_by_ref` with new value. */ 
             strcpy (from_Pascal_by_ref -> string, term); 
             from_Pascal_by_ref -> length = strlen (term); 
 
          /* Change the contents of 'from_Pascal_by_value` -- 
           * to demonstrate that the value did not get 
           * reflected back to the calling routine. 
           */ 
             from_Pascal_by_value = from_Pascal_by_desc -> dsc$w_length 
                               + from_Pascal_by_ref -> length; 
    } 
 
    else 
             printf ("\ngetenv\(\"TERM\"\) is undefined."); 
 
}   /*  End of HP C function   */ 

Example 3-13 produces the following output:


Parameters passed from Pascal: 
from_Pascal_by_value: 1 
from_Pascal_by_ref: TO_C_BY_REF 
from_Pascal_by_desc: TERM 
 
 
************************* 
After calling C_FUNCTION: 
 
by_value is still 1 
however, by_ref contains vt200-80 (aka Your Terminal Type) 
and, by_desc still contains TERM 

3.4 Sharing Global Data

The following sections describe the methods involved in sharing HP C program sections with data declared in other OpenVMS languages.

3.4.1 Sharing Program Sections with FORTRAN Common Blocks

In a FORTRAN program, separately compiled procedures can share data in declared common blocks, which specify the names of one or more variables to be placed in them. Each named common block represents a separate program section. Each procedure that declares the common block with the same name can access the same variable.

Example 3-14 shows a HP C extern variable that corresponds to a FORTRAN common block with the same name.

Example 3-14 Sharing Data with a FORTRAN Program in Named Program Sections

 
C  FORTRAN program PRSTRING.FOR contains the following lines of code: 
 
   SUBROUTINE PRSTRING 
   CHARACTER*20 STRING 
   COMMON /XYZ/ STRING 
 
   TYPE 20, STRING 
20 FORMAT (' ',A20) 
   RETURN 
   END 
 
C  End of FORTRAN program 
 
 
/*  HP C program STRING.C contains the following lines of     * 
 *  code:                                                      */ 
 
main(void) 
{ 
  #pragma extern_model common_block  // Alpha only. On VAX systems, use 
                                    // #pragma extern_model common_block shr 
  extern char xyz[20]; 
 
  strncpy(xyz,"This is a string     ", sizeof xyz); 
  prstring(); 
} 

In Example 3-14, the HP C extern variable xyz corresponds to the FORTRAN common block named XYZ. The FORTRAN procedure displays the data in the block. When sharing program sections, both programs should declare corresponding variables to be of the same type.

Note the #pragma extern_model common_block preprocessor directive. This directive sets the model for external variables to the common_block model, which is the one used by VAX C. The default external model for HP C is the relaxed_refdef model. For more information on the #pragma extern_model common_block preprocessor directive, see Section 5.4.5.

To share data in more than one variable in a program section with a FORTRAN program, the HP C variables must be declared within a structure, as shown in Example 3-15.

Example 3-15 Sharing Data with a FORTRAN Program in a HP C Structure

 
C  FORTRAN program FNUM.FOR contains the following lines of code: 
 
   SUBROUTINE FNUM 
   INTEGER*4 INUM,JNUM,KNUM 
   COMMON /NUMBERS/ INUM,JNUM,KNUM 
 
   TYPE 10, (INUM,JNUM,KNUM) 
 
10 FORMAT (3I8) 
 
   RETURN 
   END 
 
C  End of FORTRAN program 
 
 
/*  HP C program NUMBERS.C contains the following lines of    * 
 *  code:                                                      */ 
struct xs 
   { 
      int first; 
      int second; 
      int third; 
   }; 
 
#pragma extern_model common_block 
 
main() 
{ 
   extern  struct  xs  numbers; 
 
   numbers.first = 1; 
   numbers.second = 2; 
   numbers.third = 3; 
   fnum(); 
} 

In Example 3-15, the int variables declared in the HP C structure numbers correspond to the FORTRAN INTEGER*4 variables in the COMMON of the same name.

Also, note the #pragma extern_model common_block preprocessor directive. This directive sets the model for external variables to the common_block model, which is the one used by VAX C. The default external model for HP C is the relaxed_refdef model. For more information on the #pragma extern_model common_block preprocessor directive, see Section 5.4.5.

3.4.2 Sharing Program Sections with PL/I Externals

A HP PL/I variable with the EXTERNAL attribute corresponds to a FORTRAN common block and to a HP C extern variable in the common_block external model. Example 3-16 and Example 3-17 show how a program section is shared between HP C and HP PL/I.

A PL/I EXTERNAL CHARACTER attribute corresponds to a HP C extern char variable, but PL/I character strings are not necessarily null-terminated. In Example 3-16, HP C and HP PL/I use the same variable to manipulate the character string that resides in a program section named XYZ.

Example 3-16 Sharing Data with a PL/I Program in Named Program Sections

 
/*  PL/I program PRSTRING.PLI contains the following lines of code:  */ 
 
PRSTRING: PROCEDURE; 
 
   DECLARE XYZ EXTERNAL CHARACTER(20); 
 
   PUT SKIP LIST(XYZ); 
   RETURN; 
 
END PRSTRING; 
 
/*  End of PL/I program  */ 
 
 
/*  HP C program STRING.C contains the following lines of     * 
 *  code:                                                      */ 
 
main(void) 
{ 
   extern char xyz[20]; 
 
   strncpy(xyz,"This is a string    ", sizeof xyz); 
   prstring(); 
} 

The PL/I procedure PRSTRING writes out the contents of the external variable XYZ .

PL/I also has a structure type similar (in its internal representation) to the struct keyword in HP C. Moreover, HP PL/I can output aggregates, such as structures and arrays, in fairly simple stream-output statements; consider Example 3-17.

Example 3-17 Sharing Data with a PL/I Program in a HP C Structure

 
/*  PL/I program FNUM.PLI contains the following lines of code:  */ 
 
FNUM:  PROCEDURE; 
    /* EXTERNAL STRUCTURE CONTAINING THREE INTEGERS */ 
    DECLARE 1 NUMBERS EXTERNAL, 
            2 FIRST FIXED(31), 
            2 SECOND FIXED(31), 
            2 THIRD FIXED(31); 
 
    PUT SKIP LIST('Contents of structure:',NUMBERS); 
    RETURN; 
END FNUM; 
 
/*  End of PL/I program   */ 
 
 
/*  HP C program NUMBERS.C contains the following lines of    * 
 *  code:                                                      */ 
 
struct xs 
   { 
      int first; 
      int second; 
      int third; 
   }; 
 
main() 
{ 
   extern  struct  xs  numbers; 
 
   numbers.first = 1; 
   numbers.second = 2; 
   numbers.third = 3; 
   fnum(); 
} 

The PL/I procedure FNUM writes out the complete contents of the external structure NUMBERS; the structure members are written out in the order of their storage in memory, which is the same as for a HP C structure.

3.4.3 Sharing Program Sections with MACRO Programs

In a MACRO program, the .PSECT directive sets up a separate program section that can store data or MACRO instructions. The attributes in the .PSECT directive describe the contents of the program section.

Example 3-18 shows how to set up a psect in a MACRO program that allows data to be shared with a HP C program.

Example 3-18 Sharing Data with a MACRO Program in a HP C Structure

 
;  MACRO source file SET_VALUE.MAR contains the following lines of code: 
 
           .entry  set_value,^M<> 
 
           movl     #1,first 
           movl     #2,second 
           movl     #3,third 
           ret 
 
           .psect  example pic,usr,ovr,rel,gbl,noshr,- 
                   noexe,rd,wrt,novec,long 
first:     .blkl 
second:    .blkl 
third:     .blkl 
 
           .end 
 
;  End of MACRO source file 
 
 
/*  HP C program NUMBERS.C contains the following lines of    * 
 *  code:                                                      */ 
 
#pragma extern_model common_block 
 
struct xs 
   { 
      int first; 
      int second; 
      int third; 
   }  example; 
 
main() 
{ 
   set_value(); 
 
   printf("example.first = %d\n",  example.first); 
   printf("example.second = %d\n", example.second); 
   printf("example.third = %d\n",  example.third); 
} 

The MACRO program initializes the locations first, second, and third in the psect named example and passes these values to the HP C program. The locations are referenced in the HP C program as members of the external structure named example .

Also, note the #pragma extern_model common_block preprocessor directive. This directive sets the model for external variables to the common_block model, which is the one used by VAX C. The default external model for HP C is the relaxed_refdef model. For more information on the #pragma extern_model common_block preprocessor directive, see Section 5.4.5.

3.5 OpenVMS Run-Time Library Routines

The OpenVMS Run-Time Library (RTL) is a library of prewritten, commonly used routines that perform a wide variety of functions. These routines are grouped according to the types of tasks they perform, and each group has a prefix that identifies those routines as members of a particular OpenVMS RTL facility. Table 3-10 lists all the language-independent, run-time library facility prefixes and the types of tasks each facility performs.

Table 3-10 OpenVMS Run-Time Library Facilities
Facility Prefix Types of Tasks Performed
LIB$ Library routines that obtain records from devices, manipulate strings, convert data types for I/O, allocate resources, obtain system information, signal exceptions, establish condition handlers, enable detection of hardware exceptions, and process cross-reference data.
MTH$ Mathematics routines that perform arithmetic, algebraic, and trigonometric calculations.
OTS$ General-purpose routines that perform tasks such as data-type conversions as part of a compiler's generated code.
SMG$ Screen management routines that are used in designing, composing, and keeping track of complex images on a video screen.
STR$ String manipulation routines that perform such tasks as searching for substrings, concatenating strings, and prefixing and appending strings.

The OpenVMS run-time library routines are documented in detail in the following operating system documentation:

  • OpenVMS RTL Library (LIB$) Manual
  • OpenVMS VAX RTL Mathematics (MTH$) Manual
  • HP Portable Mathematics Library
  • OpenVMS RTL General Purpose (OTS$) Manual
  • OpenVMS RTL Screen Management (SMG$) Manual
  • OpenVMS RTL String Manipulation (STR$) Manual

3.6 OpenVMS System Services Routines

System services are prewritten system routines that perform a variety of tasks, such as controlling processes, communicating among processes, and coordinating I/O.

Unlike the OpenVMS Run-Time Library (RTL) routines, which are divided into groups by facility, all system services share the same facility prefix (SYS$). However, these services are logically divided into groups that perform similar tasks. Table 3-11 describes these groups.

Table 3-11 OpenVMS System Services
Group Types of Tasks Performed
AST Allows processes to control the handling of asynchronous system traps (ASTs).
Change mode Changes the access mode of particular routines.
Condition handling Designates condition handlers for special purposes.
Event flag Clears, sets, reads, and waits for event flags, and associates with event flag clusters.
Information Returns information about the system, queues, jobs, processes, locks, and devices.
Input/Output Performs I/O directly without going through RMS.
Lock management Enables processes to coordinate access to shareable system resources.
Logical names Provides methods of accessing and maintaining pairs of character-string logical names and equivalence names.
Memory management Increases or decreases available virtual memory, controls paging and swapping, and creates and accesses shareable files of code or data.
Process control Creates, deletes, and controls execution of processes.
Security Enhances the security of OpenVMS systems.
Time and Timing Schedules events and obtains and formats binary time values.

System services are documented in detail in the HP OpenVMS System Services Reference Manual.

The routines that provide a programming interface to various OpenVMS utilities are described in the OpenVMS Utility Routines Manual.


Previous Next Contents Index