HP OpenVMS Systems Documentation 
HP Pascal for OpenVMS

Previous  Contents  Index 
For every HP Pascal data type, the compiler calculates the allocation size required when a variable of the type occurs in either an unpacked or a packed context. The unpacked size is always represented in bytes, while the packed size is represented in bits.
The packed size of a variable is the minimum number of bits required to represent all values of the variable's type. In general, the compiler uses the following 32bit rules to determine the allocation size for a component of a packed structured variable:
If one of the size attributes (BIT, BYTE, WORD, LONG, QUAD, or OCTA) is applied to the variable, the size specified by the attribute represents the variable's packed size. Objects of floating point or pointer types must have a size equal to their allocation size. Ordinal types cannot exceed their maximum size, which is determined by the platform and the value of the data switch for the compile command. If no size attribute is applied to the variable, the compiler calculates the unpacked size so that it is structurally compatible with the base type of the variable's type.
Storage for variables of type VARYING OF CHAR is allocated as one byte per character, with an initial field of two bytes to indicate the total length. Storage allocation for a variable of type VARYING OF CHAR whose maximum length is less than or equal to 32 bits follows the 32bit rules in that the variable can be unaligned. On OpenVMS I64 and OpenVMS Alpha systems, variables of type VARYING OF CHAR that need alignment are aligned on a word boundary.
On OpenVMS VAX systems, variables of type VARYING OF CHAR that need alignment are aligned on a byte boundary.
Structured objects (ARRAY and RECORD) take their maximum alignment from their components, for example, if the largest object is a word, the structure is aligned on a word boundary.
The maximum size for any variable is 2^{311} bits.
Table A6 shows the allocation size for variables of each type when the variables occur in either a packed or an unpacked context.
Data Type  Unpacked Size in Bytes 
Packed Size in Bits 

INTEGER
INTEGER32 UNSIGNED UNSIGNED32 
4  32 
INTEGER64
UNSIGNED64 
8  64 
CHAR  1  8 
BOOLEAN  1 or 4 ^{1}  1 
Enumerated ^{2} 
1, if 256 elements or
fewer; 2, if more than 256 elements, or 4 ^{1} 
log2(number of elements) ^{3} + 1 
Subrange  The size of the base type  If either the upper or lower bounds contain a reference to a formal discriminant, then the size of the base type, otherwise the minimum number in which the upper and lower bounds can be expressed ^{4} 
REAL or SINGLE  4  32 
DOUBLE  8  64 
QUADRUPLE  16  128 
Pointer (OpenVMS I64 and OpenVMS Alpha systems only)  4 or 8 ^{5}  32 or 64 ^{5} 
Pointer (OpenVMS VAX systems only)  4  32 
Unpacked
ARRAY 
The sum of the unpacked sizes in bytes of all components, plus the sum of the sizes in bytes of any holes created to meet alignment requirements  Unpacked size in bytes * 8 
Unpacked
RECORD 
The sum of the unpacked sizes in bytes of the fields in the fixed part and the largest variant, plus the sum of the sizes in bytes of any holes created to meet alignment requirements  Unpacked size in bytes * 8 
PACKED
ARRAY 
The sum of the packed sizes in bits of all components, plus the sum of sizes in bits of any holes created to meet alignment requirements; this sum is rounded up to a multiple of 8 and then divided by 8  The sum of the packed sizes in bits of all components, plus the sum of sizes in bits of any holes created to meet alignment requirements; if the sum is greater than 32, the sum is rounded up to the next multiple of 8 
PACKED
RECORD 
The sum of the packed sizes in bits of all fields in the fixed part and the largest variant, plus the sum of sizes in bits of any holes created to meet alignment requirements; this sum is rounded up to a multiple of 8 and then divided by 8  The sum of the packed sizes in bits of all fields in the fixed part and the largest variant, plus the sum of sizes in bits of any holes created to meet alignment requirements; if the sum is greater than 32, the sum is rounded up to the next multiple of 8 
STRING,
VARYING OF CHAR 
Maximum length + 2  (Maximum length + 2) * 8 
Nonstatic
PACKED SET, Unpacked SET ^{3} 
32, if the set base type is a subrange of INTEGER or UNSIGNED; else, compute (ORD(upperbound of ordinal type that is base type of set's base type) + 8) DIV 8, and if this result is less than or equal to 8, the result is rounded up to 1, 2, 4, or 8  Compute (ORD (upperbound) + 1); if the result is less than or equal to 64, the result is rounded up to 8, 16, 32, or 64, and if the result is greater than 64, the result is rounded to next higher multiple of 8 
PACKED SET ^{3}  The result of (ORD(upperbound) + 8) DIV 8  Compute (ORD (upperbound) + 1); if the result is greater than 32, the result is rounded to next higher multiple of 8 
FILE  Not specified  Not specified 
The formula to compute the size of a packed subrange is MAX (X,Y) + Z where X, Y, and Z are computed as follows (LOW represents the low bound of the subrange; HIGH represents the upper bound):
IF LOW < 1 IF HIGH> 0 THEN THEN X := log2(LOW  1) + 1 Y := log2(HIGH) + 1 ELSE ELSE X := 0; Y := 0; IF LOW >= 0 THEN Z := 0 ELSE Z := 1; 
You can discover both the unpacked and packed sizes for variables of any type by using the predeclared functions BITNEXT, BITSIZE, NEXT, and SIZE, which require a parameter that is the name of either a type or a variable. These functions return the following integer values:
The maximum size for any variable is 2^{311} bits.
The following examples show the effects of packing records and multidimensional arrays at various levels.
Although packing records and arrays does save storage space and can be necessary for compatibility with other code, note that accessing unaligned variables on an OpenVMS I64 or OpenVMS Alpha system takes many more instructions than accessing variables with natural alignment, such as those in unpacked records and arrays. 
TYPE Internal_Arr = ARRAY[1..5] of 0..6; VAR Samp1_Arr : PACKED ARRAY[1..5] OF Internal_Arr; 
Each component of an array of type Internal_Arr is stored in a longword. Each component of Samp1_Arr, in turn, requires five longwords, which is enough storage space for five components of type Internal_Arr. The entire array Samp1_Arr occupies 25 longwords (800 bits).
VAR Samp1_Arr : ARRAY[1..5] OF PACKED ARRAY[1..5] OF 0..6; 
Each PACKED ARRAY[1..5] of 0..6 requires 15 bits (the range 0..6 requires 3 bits; five 3bit components requires 15 bits). Because the packed arrays are components of an unpacked array, their size is rounded up to an even 16 bits. The total size of Samp1_Arr is 80 bits.
TYPE Internal_Arr = PACKED ARRAY[1..5] OF 0..6; VAR Samp2_Arr : PACKED ARRAY[1..5] OF Internal_Arr; Samp3_Arr : PACKED ARRAY[1..5,1..5] OF 0..6; 
In this example, every component of Internal_Arr requires only three bits because the array is packed. Each component of Samp2_Arr and Samp3_Arr can be stored in 15 bits, and each array occupies 75 bits. The specification of PACKED for an array with multiple indexes results in packing at every level. The two arrays in this example are equivalent.
VAR Sample : PACKED ARRAY[1..5,1..5,1..5] OF 0..6; 
This example shows space savings for arrays of more than two dimensions when PACKED is specified at every level. The subrange 0..6 requires 3 bits; five 3bit components require 15 bits. This size describes the innermost dimension of Sample. Next, five 15bit components require 75 bits. Because of the 32bit rules, each 75bit component is rounded up to 80 bits. This size describes the middle and inner dimensions of Sample. Finally, five80bit components require 400 bits (50 bytes). The entire array Sample then requires 400 bits.
VAR Sample_Rec : PACKED RECORD Field_1 : BOOLEAN; Field_2 : INTEGER32; Field_3 : DOUBLE; END; 
In this example, Field_1 requires only 1 bit of storage. Field_2 is 32 bits in size (declared as INTEGER32) and starts immediately following Field_1. Because Field_3 is larger than 32 bits, it will start on the next byte boundary. The entire record Sample_Rec, therefore, requires 104 bits.
The memoryaddressing boundary on which a variable or a component is aligned depends on the variable's or the component's allocation size. You can change the alignment by using the ALIGNED and UNALIGNED attributes. Table A7 lists the conditions that determine boundary alignment.
Object  Arguments to the Alignment Switch  

NATURAL^{1}  VAX  
Variable declared with an alignment attribute  Specified alignment  Specified alignment 
Variable declared without an alignment attribute  Natural alignment  Byte alignment ^{2} 
Component of an unpacked array or record variable  Natural alignment  Byte alignment 
Component of a packed array or record variable  Follows the 32bit rules ^{3}  Follows the 32bit rules ^{4} 
Dynamic variables allocated by the NEW procedure  Octaword alignment on OpenVMS I64; quadword alignment on OpenVMS Alpha  Quadword alignment 
You can save storage space by packing variables of structured types, but you must be careful to pack at the proper level. Except for its alignment, a record field whose type is an unpacked array, set, or record occupies the same amount of space in a packed or an unpacked record variable. To pack such a field, you must explicitly declare its type to be packed.
When packing multidimensional arrays, you must specify packing at the innermost level to gain any significant space advantage. For example, there is no advantage in packing an array of an unpacked structured type; the unpacked components will still be aligned on byte boundaries, which leaves holes in the storage space. To gain storage space, you must specify a packed array of a packed structured type.
The following examples show the use of alignment boundaries.
Although packing records and arrays does save storage space and can be necessary for compatibility with other code, note that accessing unaligned variables on an OpenVMS I64 or OpenVMS Alpha system takes many more instructions than accessing variables with natural alignment, such as those in unpacked records and arrays. 
VAR X : [STATIC, ALIGNED(3)] INTEGER; { QUADWORD ALIGNED } { $SDATA$ on OpenVMS I64 } { $DATA$ on OpenVMS Alpha } { $LOCAL on OpenVMS VAX } 
In this example, X is declared a static variable that is aligned on a QUADWORD boundary.
VAR X : PACKED RECORD { AUTOMATIC } Field1 : BOOLEAN; Field2 : REAL; Field3 : BOOLEAN; Field4 : DOUBLE; END; 
In this example, Field1 begins at bit position 0 and is 1 bit long. Field2 begins at bit position 1 and is 32 bits long. Field3 begins at bit position 33 and is 1 bit long. However, because Field4 is greater than 32 bits long (DOUBLE requires 64 bits) Field4 must be byte aligned. For this reason, Field4 begins on bit position 40 and is 64 bits long.
VAR X : RECORD { AUTOMATIC } Field1 : [BIT(3)] 0..7; Field2 : [UNALIGNED] INTEGER32; END; 
In this example, Field1 of record X is declared to begin on bit position 0 and is 3 bits long. Due to the use of the UNALIGNED attribute on Field2, Field2 begins on bit position 3 and is 32 bits long. You can obtain the same behavior by packing record X.
Without using the UNALIGNED attribute, or without X being a PACKED record, Field2 would have been longword aligned; that is, it would have started on bit position 32. You cannot use the UNALIGNED attribute with INTEGER64 because of the 32bit rules, which states that variables greater than 32 bits must be at least bytealigned.
The following sections summarize the internal representation of the
HP Pascal data types.
This section summarizes the internal representation of VARYING OF CHAR types. A variable of type VARYING OF CHAR is stored as though it were an HP Pascal record type of the following form:
RECORD Length : [WORD] 0..Maxlength; Body : PACKED ARRAY[1..Maxlength] OF CHAR; END; 
Figure A1 shows the storage allocated for a variable of type VARYING[8] OF CHAR.
Figure A1 Storage of Varying Data
The predefined schema type STRING uses VARYING OF CHAR as its underlying data type, so Figure A1 also represents the STRING type.
The following sections summarize the internal representation of singleprecision (F_floating and S_floating), doubleprecision (D_floating, G_floating, and T_floating), and quadrupleprecision (H_floating and X_floating) floatingpoint numbers.
An F_floatingpoint value is represented by four contiguous bytes. The bits are numbered from the right, 0 through 31, as shown in Figure A2.
Figure A2 F_floatingPoint Data Representation
An F_floatingpoint value is specified by its address A, the address of the byte containing bit 0. The form of this value is sign magnitude as follows:
An S_floatingpoint value is represented by four contiguous bytes. The bits are numbered from the right, 0 through 31, as shown in Figure A3.
Figure A3 S_floatingPoint Data Representation
An S_floatingpoint value is specified by its address A, the address of the byte containing bit 0. The form of this value is sign magnitude as follows:
Previous  Next  Contents  Index 