[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

HP Pascal for OpenVMS
Language Reference Manual


Previous Contents Index

10.2.30 PEN_CHECKING_STYLE

HP Pascal in cooperation with the OpenVMS Linker performs compile-time and link-time checks to ensure that all compilations that inherit environment files actually used the same environment file definition. Information is placed in the object file such that the OpenVMS Linker will perform the same check between each object file that inherited environment files.

By default, compilation units that inherit an environment file compare the embedded compilation time inside the environment file against uses found in any other environment files that are also inherited. If the times are different, a compile-time message is displayed. This happens on all systems.

This checking can be disabled or modified by using the PEN_CHECKING_STYLE attribute in the Pascal source file that created the environment file. Once the environment file exists, its selected checking style will be performed at each use.

The PEN_CHECKING_STYLE attribute is valid at the beginning of a MODULE that creates an environment. The syntax is:


PEN_CHECKING_STYLE(keyword)

In this syntax, keyword is:

  • COMPILATION_TIME
    Uses the compilation time of the environment file in all subsequent compile-time checking for users of this environment file. This is the default.
  • IDENT_STRING
    Uses the [IDENT()] string of the environment file in all subsequent compile-time checking for users of this environment file.
  • NONE
    Disables all compile-time checking for users of this environment file.

10.2.31 POS

The POS attribute forces the field to a specific bit position within the record.


POS( n )

n

The constant expression n specifies the bit location, relative to the beginning of the record, at which the field begins.

Usage and Default Information:

  • You can apply the POS attribute to a field of a packed or an unpacked record.
  • The constant expression n cannot denote a negative integer.
  • The beginning position of a field must be greater than the ending position of the field preceding it.
  • The POS attribute cannot be used on a field that follows (not necessarily immediately) a field whose type has run-time size and is nonstatic.
  • Inside a record variant, the beginning position of a field must be greater than the ending position of the preceding field within the same variant. The variants themselves can overlap.
  • A field whose allocation size is greater than 32 bits must be positioned according to the allocation size rules for the platform.
  • A record variable containing a field of a file type cannot include a POS attribute for any field.
  • The specified bit position must not conflict with the alignment explicitly required by an alignment attribute.
  • Two record types in which corresponding fields are not identically positioned are neither assignment compatible nor structurally compatible.

Consider the following example:



TYPE
   Control = RECORD
      Flag_1 : [ BIT, POS( 0 ) ] BOOLEAN;
      Flag_2 : [ BIT, POS( 1 ) ] BOOLEAN;
      Count  : [ BYTE, ALIGNED ] 0..100;
      Error  : [ BIT, POS( 31 ) ] BOOLEAN;
      END;

This example uses the POS attribute to position the fields of an unpacked record such that Flag_1 occupies bit 0, Flag_2 occupies bit 1, and Error occupies bit 31. Because the Count field has size and alignment attributes, it is allocated one byte of storage and is aligned on the byte boundary following Flag_2; that is, storage for Count occupies bits 8 through 15. Bits 2 through 7 and 16 through 30 are left empty; you cannot refer to them.

For More Information:

10.2.32 PSECT

The PSECT attribute is useful for placing static variables and executable blocks in program sections that are shared among executable images.


   [ PSECT [[ ( { identifier } ) ]] ]

identifier

Identifier passed designating the program section in which storage for a variable, routine, or compilation is to be allocated. If you omit the identifier, the name of the variable is used as the name of the program section.

Usage and Default Information:

  • A variable having the AT, COMMON, or PSECT attribute is implicitly static.
  • PSECT is the only allocation attribute that can be applied to routines and compilation units.

For More Information:

  • On default allocation for variables declared in the outermost block of a program or in nested blocks ( Section 10.2.5)
  • On default allocation for variables declared in the outermost block of a module ( Section 10.2.36)
  • On program sections (Appendix A)

10.2.33 QUAD

The QUAD attribute specifies the amount of storage in quadwords to be received by the object.


QUAD [[( n )]]

The optional constant n indicates the number of quadword storage units.

For More Information:

10.2.34 READONLY

The READONLY attribute specifies that an object can be read by a program but it cannot have values assigned to it.

Usage and Default Information:

  • You can apply this attribute to variables, formal parameters, the base types of pointer variables, and components of structured variables.
  • By default, an object can be both read and written.
  • No value of any type is assignment compatible with a read-only object.
  • The presence of a read-only component in an object of a structured type prohibits the object from having values assigned to it.
  • You can only pass a read-only actual VAR parameter to a read-only formal VAR parameter.
  • A pointer expression whose base type is read-only is assignment compatible only with a pointer variable whose base type is also read-only.

Consider the following example:



TYPE
   t = RECORD
      i : INTEGER;
      END;
   P_Read_Only = ^ [READONLY] t;
VAR
   Pro : P_Read_Only;
   Prw : ^ T;

PROCEDURE q( p : P_Read_Only);
   VAR
      x : INTEGER;
   BEGIN
   x := p^.i;
   {More statements...}
   END;
{In the executable section:}
NEW( Pro ):
NEW( Prw );
Q( Pro );
Q( Prw );
Prw^.I := 0;

This example shows the declaration of two pointer variables, Pro and Prw, and the calls to NEW that create the dynamic variables Pro^ and Prw^. The type of the formal parameter p requires that a corresponding actual parameter have read access; therefore, both Pro and Prw can legally be passed to Q as actual parameters. Because P is a READONLY parameter, the value of the dynamic variable P^ (which corresponds to either Pro^ or Prw^) can be assigned to a variable, as shown in the assignment statement in the body of Q. However, only Prw^ can have values assigned to it, as shown in the last statement.

For More Information:

10.2.35 REFERENCE

The REFERENCE attribute causes the formal parameter value in a routine to be passed by reference using foreign semantics.

Usage and Default Information:

  • The REFERENCE attribute is not allowed on formal parameters of schema types.

Consider the following example:



PROCEDURE Test1( P1 : [REFERENCE] INTEGER;
                 P2 : [IMMEDIATE] INTEGER ); EXTERNAL;

This example defines a procedure, Test1, which has two parameters. The first parameter, P1, is passed by reference. The second parameter, P2, is passed by immediate value.

For More Information:

10.2.36 STATIC

The STATIC attribute causes HP Pascal to create a static object, which is allocated only once and exists as long as the executable image in which it is allocated remains active.

Usage and Default Information:

  • You can override the default (automatic) for variables declared in nested blocks or in the outermost level of compilation units by specifying the STATIC attribute on the variable.
  • By default, variables declared at the outermost level of a module are static.
  • Global and external variables are implicitly static so they conflict with the AUTOMATIC attribute.
  • A variable having the AT, COMMON, or PSECT attribute is implicitly static.
  • Allocation attributes can not be applied to nonstatic types.

Consider the following example:



PROGRAM Print_Random( OUTPUT );

VAR
   i : [AUTOMATIC] INTEGER;

FUNCTION Random : INTEGER;
   VAR
      x : [STATIC] INTEGER VALUE 15;
   BEGIN
   x := (( 9 * x ) + 7 ) MOD 11;
   Random := x;
   END;
{In the executable section:}
FOR i := 1 TO 20 DO
   WRITELN( Random );
END.

The program Print_Random includes a function that generates a random integer. Because the variable x is declared STATIC, its value is preserved from one activation of the function to the next. By default, the storage for x would have been deallocated when control returned to the main program. Because x is static, it retains the value it had when Random ended and assumes this value the next time Random is called. In the program Print_Random, the program-level variable i is declared AUTOMATIC.

For More Information:

10.2.37 TRUNCATE

The TRUNCATE attribute indicates that an actual parameter list for a routine can be truncated at the point that the attribute was specified. You can use TRUNCATE with the PRESENT function.

Usage and Default Information:

The examples in this list are based on this PROCEDURE declaration from Example 10-1, which shows the use of the TRUNCATE attribute with default values:



PROCEDURE p( a : [TRUNCATE] CHAR := 'a';
             b :            CHAR := 'b';
             c : [TRUNCATE] CHAR := 'c';
             d :            CHAR := 'd' );

  • You can specify the TRUNCATE attribute on a formal parameter in a routine declaration.
  • If a parameter with the TRUNCATE attribute is present in the actual parameter list (explicitly with a null actual parameter, or by being skipped over by a nonpositional actual parameter), then the list is not truncated at the TRUNCATE parameter. All parameters (including the current TRUNCATE parameter) up to the next parameter that specifies TRUNCATE must be present or have a default value. The first parameter is present in this call from Example 10-1 so the list is not truncated at the first parameter. The second parameter has a default value so it is included in the result. The third parameter, however, is not present in the actual parameter list so the parameter list is truncated:


    
    p();           { DEFAULT a AND b--TRUNCATE AT c "ab"   }
    
    
  • If a parameter with the TRUNCATE attribute is present by default, the list is not truncated at that point. In this line of code from Example 10-1, the first, second, and third parameters are present by default. Because the third parameter is present, the parameter list is not truncated and all four parameters are present in the result.


    
    p(,,);         { DEFAULT a, b, c AND d          "abcd" }
    
    
  • You can specify actual parameters either positionally or nonpositionally; it is the order in the formal parameter list that is used to determine where the list has been truncated and which parameters are required. Because c, the third parameter, is present in the actual list, the parameter list is not truncated.


    
    p( c := y );   { DEFAULT a, b AND d             "abyd" }
    
    
  • If a parameter is positioned after the TRUNCATE parameter in the formal parameter list and is present (explicitly with a null actual parameter or by being skipped over by a nonpositional actual parameter), then the list is not truncated at the TRUNCATE parameter. Any parameters after the TRUNCATE parameter must be present or have a default value.

In Example 10-1, each call to procedure p in the main body of the program has a comment that shows the expected parameter list behavior and the expected output. The parameter list is truncated at either parameter a or parameter c.

If parameters b and d did not have default values, the call p( w ) or p( w, x, y ) would be illegal because the list cannot be truncated at the second or fourth positions.

Example 10-1 Using the TRUNCATE Attribute


PROGRAM Trunc( OUTPUT );
VAR
   w   : CHAR VALUE 'w';
   x   : CHAR VALUE 'x';
   y   : CHAR VALUE 'y';
   z   : CHAR VALUE 'z';
PROCEDURE p( a : [TRUNCATE] CHAR := 'a';
             b :            CHAR := 'b';
             c : [TRUNCATE] CHAR := 'c';
             d :            CHAR := 'd' );
   BEGIN
   IF PRESENT( a ) THEN WRITE( a );
   IF PRESENT( b ) THEN WRITE( b );
   IF PRESENT( c ) THEN WRITE( c );
   IF PRESENT( d ) THEN WRITE( d );
   WRITELN;
   END;
{In the executable section:}
{ CALL              LIST                          RESULT  }
 p;               { NO PARAMETERS--TRUNCATE AT a   ""     }
 p();             { DEFAULT a AND b--TRUNCATE AT c "ab"   }
 p(,);            { DEFAULT a AND b--TRUNCATE AT c "ab"   }
 p(,,);           { DEFAULT a, b, c AND d          "abcd" }
 p(,,,);          { DEFAULT a, b, c AND d          "abcd" }
 p( w );          { DEFAULT b--TRUNCATE AT c       "wb"   }
 p( w, x );       { TRUNCATE AT c                  "wx"   }
 p( w, x, y );    { DEFAULT d                      "wxyd" }
 p( w, x, y, z ); { NO DEFAULTS                    "wxyz" }
 p( a := w );     { DEFAULT b--TRUNCATE AT c       "wb"   }
 p( b := x );     { DEFAULT a--TRUNCATE AT c       "ax"   }
 p( c := y );     { DEFAULT a, b AND d             "abyd" }
 p( d := z );     { DEFAULT a, b AND c             "abcz" }

For More Information:

10.2.38 UNALIGNED

The UNALIGNED attribute specifies that an object can be aligned on any bit boundary.

Usage and Default Information:

  • Alignment attributes are illegal on nonstatic types, components of files, and on VARYING OF CHAR strings.
  • An unaligned variable must have an allocation size that conforms to the rules for the platform.
  • A formal parameter cannot be unaligned so an unaligned variable cannot be passed to a formal variable parameter.
  • The base type of a pointer variable passed to the NEW procedure cannot have alignment greater than a quadword, nor can it be unaligned.

For More Information:

10.2.39 UNBOUND

The UNBOUND attribute specifies that a routine does not access automatic variables outside the scope in which it is declared. That is, the bound procedure value of an unbound routine does not include the static scope pointer.

Usage and Default Information:

  • You can apply this attribute to routines and formal routine parameters.
  • In the absence of an UNBOUND attribute, the compiler assumes that the bound procedure value of a routine includes the static scope pointer.
  • By default, all predeclared routines and all routines declared at program or module level have the characteristics of unbound routines. All routines declared in nested blocks are considered bound unless they have an UNBOUND, GLOBAL, WEAK_GLOBAL, or INITIALIZE attribute.
  • All routines called from within the block of an unbound routine must be local to the unbound routine, or be unbound, whether by default or by an explicit attribute.
  • Nonlocal variables accessed from within the block of an unbound routine cannot have automatic allocation.
  • If a formal routine parameter is unbound, all actual routine parameters passed to it must also be unbound.
  • You can pass an unbound routine as an actual parameter to a formal routine parameter that is not unbound.

Consider the following example:



[EXTERNAL] FUNCTION f( [IMMEDIATE, UNBOUND] PROCEDURE Count )
   : BOOLEAN; EXTERNAL;

PROCEDURE a;
   VAR
      i : [STATIC] INTEGER;
      b : BOOLEAN;

   [UNBOUND] PROCEDURE p;
      BEGIN
      i := i + 1;
      {Additional statements...}
      END;
   b := f( p );
   END;

This example shows the declaration of the unbound procedure p and the unbound formal procedure parameter Count. The executable section of p cannot access variables declared in the enclosing block of procedure a unless those variables are statically allocated. Procedure p can access the variable i, which is declared with the STATIC attribute, but it cannot access the variable b that is automatically allocated. Because the formal parameter Count is unbound, only other unbound routines (such as p) can be passed to function f as actual parameters. Count must be declared UNBOUND because it is passed by immediate value.

For More Information:

10.2.40 UNSAFE

The UNSAFE attribute indicates that an object can accept values of any type without type checking. The exact properties of an unsafe object depend on the object's machine representation.

Usage and Default Information:

  • You can apply this attribute to variables, formal parameters, formal discriminants, the base types of pointer variables, components of structured variables, function results, and the types of other data items listed in Table 10-9.
  • A conformant VARYING parameter or a formal schema parameter cannot be declared UNSAFE.
  • UNSAFE is the only attribute allowed on schema formal discriminants.
  • An expression of any type is assignment compatible with an unsafe object. However, neither the expression nor the object can contain a file component. If the machine representations of the expression and the unsafe object differ, the compiler forces them to have the same number of bits by modifying the value of the expression as follows:
    • Assignment to a variable with the UNSAFE attribute causes the value of the right-hand side to be truncated or zero-extended to the bit size of the left-hand variable. Note this can not always be its natural bit size; for example, if the variable you are assigning a value to was declared with an explicit size attribute. If that value is the legal value of the left-hand type, then the assignment occurs; otherwise, the variable is undefined.
    • The UNSAFE attribute has no effect on variable fetches.

    Consider the following example:


    
    v : [LONG, UNSAFE] ( aa, bb, cc );
    
    

    As an enumeration of less than 256 elements, its natural size can be less than a longword. Because of the LONG attribute, it is allocated a longword in memory. However, fetches from the variable might be smaller because the explicit size attribute has no effect on any fetches. Assignments correctly assign the natural size portion of V, but the contents of the extra bits are zero-extended at the assignment.
  • A pointer expression is assignment compatible with a pointer variable whose base type is unsafe only if the base types have the same allocation size and if they have compatible alignment, READONLY, VOLATILE, and WRITEONLY attributes.
  • You can pass an actual parameter variable to an unsafe formal VAR parameter if the types have the same allocation size and if they have compatible alignment, READONLY, VOLATILE, and WRITEONLY attributes.
  • When a formal parameter is an unsafe conformant array, the HP Pascal compiler must be able to establish bounds for the corresponding actual parameter that exactly describe the amount of storage the parameter occupies. If the conformant array is one-dimensional, the actual parameter need not be an array. The compiler constructs the bounds of the formal array so that the actual parameter and the formal array have the same size.
    For this construction to be possible, the size of the actual parameter must be an exact multiple of the size of the formal array component. The compiler chooses the low bound of the formal parameter's index to be the smallest possible value of the index type. If the formal conformant parameter is a multidimensional array with n dimensions, the actual parameter must be an array having no fewer than n - 1 dimensions. The first n - 1 dimensions of the two arrays will have identical array bounds. The compiler chooses bounds for the last dimension of the conformant array so that the conformant as a whole describes the exact size of the actual parameter.

    HP Pascal allows you to pass an actual parameter of a schema type to the an unsafe conformant array; however, because HP Pascal cannot determine the size of the actual parameter until run time, you must be sure that the actual parameter is an exact multiple of the size of the formal array component.

Consider the following example:



PROGRAM Output_Buffer( Data_File );
TYPE
   Natural = 0..MAXINT;
VAR
   Data_File : FILE OF ARRAY[0..511] OF CHAR;
   Int_Array : ARRAY[0..1023] OF INTEGER;
   A_String  : VARYING[2048] OF CHAR;
   Chr_Array : ARRAY[0..4095] OF CHAR;
   Status    : BOOLEAN;

FUNCTION Put_Buf( VAR Buffer :
                  [UNSAFE] ARRAY[ a..b : Natural ] OF CHAR )
           : BOOLEAN;
   VAR
      Cur : [STATIC] INTEGER VALUE 0;
      i   : INTEGER;
   BEGIN
   FOR i := a TO b DO
      BEGIN
      Data_File^[Cur] := Buffer[i];
      Cur := Cur + 1;
      IF Cur > 511 THEN
         BEGIN
         PUT( Data_File);
         Cur := 0;
         END;
      END;
   Put_Buf := (Cur = 0);
   END;
{In the executable section:}
Status := Put_Buf( Int_Array );
Status := Put_Buf( A_String );
Status := Put_Buf( Chr_Array );

The function Put_Buf assigns successive components of the conformant array parameter to the file buffer variable of Data_File. If Data_File^ is filled, the function returns TRUE; otherwise, it returns FALSE.

The program issues three calls to Put_Buf. In the first and second calls, the actual parameters are not of the same type as the formal parameter Buffer. However, because Buffer has the UNSAFE attribute, it accepts an actual parameter of any type and treats it as though it were an array of characters. The third call to Put_Buf passes an actual parameter of the same type as the formal parameter.

For More Information:


Previous Next Contents Index