 |
» |
|
|
 |
The following table summarizes the differences in storage
allocation between HP C and HP Pascal. The footnote numbers refer
to notes located in a section immediately following the table. Table 3-1 HP C versus HP Pascal Storage Allocation HP C Type | HP C Description | Corresponding HP Pascal Type | HP Pascal Description |
|---|
char, signed char | 1 byte, byte aligned |
| 1 byte, byte aligned; Subrange: -128
.. 127 | unsigned char | 1 byte, byte aligned | char | 1 byte, byte aligned; Subrange: 0 .. 255 | short | 2 bytes, 2-byte aligned | shortint | Subrange: -32768..32767 | unsigned short | 2 bytes, 2-byte aligned |
| Subrange: 0 .. 65535 | int | 4 bytes, 4-byte aligned | integer | 4 bytes, 4-byte aligned; Subrange: -2147483648
.. 2147483647 | unsigned int | 4 bytes, 4-byte aligned |
| 4 bytes, 4-byte aligned; Subrange: 0
.. 4294967295 | long | 4 bytes, 4-byte aligned (8 bytes in LP64) | integer | Subrange: -2147483648 .. 2147483647 | unsigned long | 4 bytes, 4-byte aligned (8 bytes in LP64) |
| 4 bytes, 4-byte aligned; Subrange: 0
.. 4294967295 | (See Note 1) |
| longint | 8 bytes, 4-byte aligned | float | 4 bytes, 4-byte aligned | real | 4 bytes, 4-byte aligned | double | 8 bytes, 8-byte aligned | longreal | 8 bytes, 8-byte aligned | long double | 16 bytes, 16-byte aligned |
|
| enum | 4 bytes, 4-byte aligned | enumeration or integer (See Note 2) | 1 byte if fewer than 257 elements; 2 bytes
if between 257 and 65536; otherwise, 4 bytes. 1, 2, or 4-byte aligned. | char enum | 1 byte, 1-byte aligned |
| 1 byte, 1-byte aligned, subrange: -128..127 | short enum | 2 bytes, 2-byte aligned | short int | subrange: -32768..32767 | int enum | 4 bytes, 4-byte aligned | integer | 4 bytes, 4-byte aligned, subrange: -2,147,483,648..2,147,483,647 | long enum | 4 bytes, 4-byte aligned | integer | 4 bytes, 4-byte aligned, subrange: -2,147,483,648..2,147,483,647 | array [n] of type | Size is number of elements times element size.
Align according to element type. | ARRAY [0 .. n-1] OF type (See Note
3) | Size is the number of elements times
element size. Align according to element type. | array [n] of char | [n] bytes, byte aligned | PACKED ARRAY [0 .. n-1] OF CHAR or not PACKED (See Note 4) | [n] bytes, byte aligned | struct (See Note 5) | Pascal string descriptors may be emulated using
C structures, see the note for an example. | STRING [n] | Size 4+[n]+1 bytes, 4-byte aligned. | Pointer to string descriptor structure
(See Note 6) | Pascal VAR parameters may be emulated using C pointers to string descriptor structures. (See
Note 6). | STRING |
| char * | Pointer to a null terminated array of characters | pointer to character array | (See Note 7) | struct | Size of elements plus padding, aligned according
to largest type | record | (See Note 8) | union | Size of elements plus padding, aligned according
to largest type | (untagged) variant record (See
Note 9) | (See Note 8) | signed bit-fields |
| packed record (See Note 10) |
| unsigned bit-fields |
| packed record (See Note 11) |
| void |
| Used when calling an HP Pascal procedure (See
Note 12) |
| pointer | 4 bytes, 4-byte aligned (8 bytes in LP64) | pointer to corresponding type | 4 bytes, 4-byte aligned | long pointer | 8 bytes, 8-byte aligned | $ExtnAddr$ pointer or $ExtnAddr$ VAR parameter | 8 bytes, 4-byte aligned | char | 1 byte, 1-byte aligned | boolean (See Note 13) | 1 byte, 1 byte aligned | void function parameter | 4 bytes, 4-byte aligned | PROCEDURE parameter | 4 bytes, 4-byte aligned | function parameter | 4 bytes, 4-byte aligned | FUNCTION parameter | 4 bytes, 4-byte aligned | struct of 1-bit fields | (See Note 14) | set |
|
| Pascal files may be read by C programs with
some effort. (See Note 15) | file | external record oriented file | pointer to void function |
| procedure |
| pointer to function |
| function |
|
Notes
on HP C and HP Pascal |  |
The longint type in HP Pascal is a 64-bit signed integer.
A corresponding HP C type could be any structure or array of 2 words; however,
HP C cannot directly operate on such an object. By default, HP C enumerations are allocated 4 bytes
of storage, while HP Pascal enumerations use the following scheme: 1 byte, if fewer than 257 elements. 2 bytes, if between 257 and 65536 elements.
If the default enumeration specifier is modified with a char or short type specifier, 1 or 2 bytes of storage are allocated.
See Table 3-1 for a description of the sized enumerated types. This is important if the items are packed. For example, a
25-element enumeration in HP Pascal can use 1 byte and be on a byte
boundary, so you must use the HP C type char or a sized enum declaration char enum. HP C always indexes arrays from zero, while HP Pascal
arrays can have lower bounds of any user-defined scalar value. This
is only important when passing an array using an index to subscript
the array. When passing the subscript between HP C and HP Pascal,
you must adjust the subscript accordingly. HP C always passes a
pointer to the first element of an array. To pass an array by value,
enclose the array in a struct and pass the struct. HP C char arrays are packed one character per byte, as are
HP Pascal arrays (even if PACKED is not used). HP Pascal permits certain
string operations with a packed array of char when the lower bound is one. The HP Pascal type STRING [n] uses a string descriptor that consists of the following:
a word containing the current length of the string, n bytes for the characters, and an extra byte allocated
by the HP Pascal compiler. Thus, the HP Pascal type STRING[10] corresponds to the following HP C structure: typedef struct { int cur_len; /* 4 bytes */ char chars [10]; /* 10 bytes */ char extra_byte; /* 1 byte */ } STRING_10; which is initialized like this: STRING_10 this_string = { 0, /* The current length */ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* The 10 bytes */ 0 /* The null byte */ }; Both the C structure and the Pascal string are 4-byte aligned. HP Pascal also has a generic string type in which
the maximum length is unknown at compile time. Objects of this type
have the same structure as in Note 5 above; the objects are only used
as VAR formal parameters. A variable of this type is a pointer to a character
array if the string is null-terminated; HP Pascal will not handle
the null byte in any special way. An HP C parameter of type "pointer
to char" corresponds to an HP Pascal VAR parameter of
type "packed array of char." However, the type definition of that VAR parameter
must have the bounds specified. The size is equal to the size of all members plus
any padding needed for the alignment. (See Chapter 2 for details
on alignment.) The alignment is that of the member with the strictest
alignment requirement. A union corresponds directly to an untagged HP Pascal
variant record. For example, the HP C union: typedef union { int i; float r; unsigned char c; } UNIONTYPE; corresponds to: TYPE UNIONTYPE = RECORD CASE INTEGER OF 1 : (i : INTEGER); 2 : (r : REAL); 3 : (c : CHAR); END; The tagged HP Pascal variant record: TYPE TAGGED_UNIONTYPE = RECORD CASE tag : INTEGER OF 1 : (i : INTEGER); 2 : (r : REAL); END; corresponds to this HP C structure: typedef struct { int tag; union { int i; float r; }; } TAGGED_UNIONTYPE; HP Pascal subranges with a negative value as their
lower bound have enough bits allocated to contain the upper bound,
with an extra bit for the sign. Thus, the HP C structure: typedef struct { int b1 : 1; int b2 : 2; int b3 : 3; int b4 : 4; int b5 : 5; int b6 : 6; int b7 : 7; } BITS; corresponds to the following untagged HP Pascal record: TYPE BITS = PACKED RECORD b1 : BOOLEAN; b2 : -2 .. 1; b3 : -4 .. 3; b4 : -8 .. 7; b5 : -16 .. 15; b6 : -32 .. 31; b7 : -64 .. 63; END; Unsigned bit-fields map onto HP Pascal packed record
fields whose types are the appropriate subranges. For example, the
HP C structure: typedef struct { unsigned int b1 : 1; unsigned int b2 : 2; unsigned int b3 : 3; unsigned int b4 : 4; unsigned int b5 : 5; unsigned int b6 : 6; unsigned int b7 : 7; } BITS; corresponds to this untagged HP Pascal record: TYPE BITS = PACKED RECORD b1 : 0 .. 1; b2 : 0 .. 3; b3 : 0 .. 7; b4 : 0 .. 15; b5 : 0 .. 31; b6 : 0 .. 63; b7 : 0 .. 127; END; The type void, when applied to a function declaration, corresponds to
an HP Pascal procedure. HP Pascal allocates one byte for Boolean variables, and only accesses the rightmost bit
to determine its value. HP Pascal uses a 1 to represent true and
zero for false; HP C interprets any nonzero value
as true and interprets zero as false. HP Pascal sets are packed arrays of unsigned bits.
For example, given the HP Pascal set: TYPE SET_10 = SET OF 0 .. 9; VAR s: SET_10; the corresponding HP C struct would be: typedef struct { unsigned int b0 : 1; unsigned int b1 : 1; unsigned int b2 : 1; unsigned int b3 : 1; unsigned int b4 : 1; unsigned int b5 : 1; unsigned int b6 : 1; unsigned int b7 : 1; unsigned int b8 : 1; unsigned int b9 : 1; } SET_10; SET_10 s; Also, the following operation in HP Pascal: s := s + [9]; has the following corresponding HP C code: s.b9 = 1; HP C and HP Pascal file types and I/O operations
do not correspond.
Passing
Parameters Between HP C and HP Pascal |  |
This section describes additional information on parameter
passing. All HP C parameters are passed by value except arrays and functions,
which are always passed as pointers. Reference parameters to HP
Pascal can be implemented in two ways: first, by passing the address
of an object by applying the address operator & to the variable; second, by declaring a variable
to be a pointer to such a type, assigning an address to the pointer
variable, and passing the pointer. If an HP Pascal procedure or function has a parameter that
is an array by value, it can be called from HP C by passing a struct that contains an array of the corresponding type. Be careful when passing strings to HP Pascal. If
the routine expects a packed array of char, be sure to pass a char array. If the routine expects a user-defined string,
pass the structure declared in Note 5 above. The examples below are HP Pascal and HP C source files that
show the parameter passing rules. The HP Pascal file contains 2 subroutines, pass_char_arrays() and pass_a_string(). The HP C file contains the main line routine
that calls these two subroutines and displays the results. The HP
C program is annotated with the expected results. The following is the HP Pascal procedure called from HP C: $subprogram$ program p; const len = 10; type pac_10 = packed array [1..10] of char; string_10 = string [len]; function pass_char_arrays (a: pac_10; var b: pac_10; c: string_10; var d: string_10) : integer; var i : integer; ret_val : integer; begin ret_val := 0; for i := 1 to len - 1 do begin if ( a[i] <> 'a' ) then ret_val := 1; a[i] := 'z'; if ( b[i] <> 'b' ) then ret_val := 256; b[i] := 'y'; end; for i := 1 to strlen (c) do begin if ( c[i] <> 'c' ) then ret_val := 65536; c[i] := 'x'; end; for i := 1 to strlen (d) do begin if ( d[i] <> 'd' ) then ret_val := maxint; d[i] := 'w'; end; pass_char_arrays := ret_val; end; function pass_a_string (var a: string) : integer; var i : integer; ret_val : integer; begin ret_val := 0; for i := 1 to strlen (a) do begin if (a[i] <> 'x' ) then ret_val := maxint; a[i] := 'q'; end; pass_a_string := ret_val; end; begin end. The following HP C main program calls the HP Pascal procedure: #include <stdio.h> #include <string.h> static struct string_10 { int cur_len; char chars[10]; }; /* a Pascal routine */ extern int pass_char_arrays (/* pac10, var pac10, string_10, var string[10] */); main(void) { static struct string_10 a, b, c, d; int ret_val; strcpy (a.chars, "aaaaaaaaa"); strcpy (b.chars, "bbbbbbbbb"); strcpy (c.chars, "ccccccccc"); c.cur_len = strlen (c.chars); strcpy (d.chars, "ddddddddd"); d.cur_len = 5; ret_val = pass_char_arrays (a.chars, b.chars, &c, &d); printf ("a: %s\n", a.chars); /* prints aaaaaaaaa */ printf ("b: %s\n", b.chars); /* prints yyyyyyyyy */ printf ("c: %s\n", c.chars); /* value parm prints xxxxxxxxx */ printf ("d: %s\n", d.chars); /* prints wwwwwdddd */ printf ("return mask: %d\n", ret_val); /* print 0 */ ret_val = pass_a_string (&c); printf ("c: %s\n", c.chars); /* prints qqqqqqqqq */ printf ("return mask: %d\n", ret_val); /* print 0 */ return 0; } The program produces the following output: a: aaaaaaaaa b: yyyyyyyyy c: xxxxxxxxx d: wwwwwdddd return mask: 0 c: qqqqqqqqq return mask: 0 The routine pass_a_string() expects a generic string (described in Note 6
above), so you must pass an extra argument. The extra argument consists
of a value parameter containing the maximum length of the char array. HP Pascal routines do not maintain a null byte at
the end of HP C strings. HP Pascal determines the current length
of the string by maintaining the length in a 4-byte integer preceding
the character data. When an HP Pascal procedure or function (that
takes as a parameter a string by reference) is called, the following
code is necessary if the Pascal routine modifies the string: pass_a_string (a, temp); /* From note 2 above */ a.chars[a.cur_len] = '\0'; In non-ANSI mode, HP C promotes most float (32-bit) arguments to double (64-bit). Therefore, all arithmetic using objects
defined as float is actually using double code. Float code is only used when the float objects are stored. In ANSI mode where function prototypes have been declared
with a float parameter, no automatic promotion is performed.
If the prototype is within the current scope, floats will not be automatically promoted. To call an HP Pascal routine that expects an argument of type REAL (32-bits), you may either declare a function prototype
in ANSI mode, use the +r command line option in non-ANSI mode to always
pass floats as floats, or declare the actual parameter as a struct with a float as its only field, such as: typedef struct {float f;} PASCAL_REAL_ARG; HP Pascal global data can usually only be accessed
by HP C if the data is declared at the outermost level. HP Pascal
stores the names of the objects in lowercase letters. For example, the HP Pascal global: PROGRAM example; VAR PASCAL_GLOBAL: INTEGER; BEGIN END. is accessed by HP C with this declaration: extern int pascal_global;
The Pascal compiler directives $GLOBAL$ and $EXTERNAL$ can be used to share global data between HP Pascal
and HP C. The $EXTERNAL$ directive should be used to reference C globals
from a Pascal subprogram. The $GLOBAL$ directive should be used to make Pascal globals
visible to other languages such as HP C. It should be used if it
is necessary to share globals when calling C functions from a Pascal program. Linking
HP Pascal Routines on HP-UX |  |
When calling HP Pascal routines, you must include the HP Pascal run-time
libraries by adding the following option to the cc command line: -lcl Additionally, the -lm option may be necessary if the Pascal routines
use the Pascal predefined math functions. For details on linking external libraries, see the -l option of the cc(1) and ld(1) commands in the HP-UX Reference manual.
|