[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.41 VALUE

The VALUE attribute causes the variable to be a reference to an external constant or to be the defining point of a global constant.

Usage and Default Information:

  • You can only use the VALUE attribute on a variable that has the EXTERNAL or GLOBAL attribute.
  • A value variable with global visibility must be initialized in the VAR, TYPE, or VALUE declaration sections.
  • You cannot apply the VALUE attribute to variables larger than 64 bits on OpenVMS I64 and OpenVMS Alpha systems or 32 bits on OpenVMS VAX systems.
  • The VALUE attribute is legal only on ordinal or real types.
  • The VALUE attribute causes the READONLY attribute to be placed on the variable.

In this example, the linker resolves the reference to CLI$_PRESENT; the example writes the decimal value to OUTPUT. The example also defines a global symbol with the name My_Global and with a value of 1985.



PROGRAM Value_Test( OUTPUT );
VAR
   CLI$_PRESENT : [VALUE, EXTERNAL] INTEGER;
   My_Global : [VALUE, GLOBAL] INTEGER VALUE 1985;
{In the executable section:}
WRITELN( 'The value is', CLI$_PRESENT );

For More Information:

10.2.42 VOLATILE

The VOLATILE attribute indicates to the compiler that the value of an object is subject to change at unusual points in program execution. Normally, during execution, an object's value changes only under the following circumstances:

  • When another value is assigned to it
  • When it is passed as a writable VAR parameter
  • When it is read into by a READ, READLN, or READV procedure
  • When it is used as the control variable of a FOR loop

In addition, the compiler expects to evaluate the object only when it appears in an expression.

The value of a volatile object can change as the result of an action not directly specified in the program. Thus, the compiler assumes that the value of a volatile object can be changed or evaluated at any time during program execution. Consequently, a volatile object does not participate in any optimization based on assumptions about its value.

The behavior of many device registers, and modifications by asynchronous processes and exception handlers, are two examples that demonstrate volatile behavior.

Usage and Default Information:

See Table 10-6, which also summarizes combinations of volatile and nonvolatile parameters and variables accepted by the compiler.

  • You can apply this attribute to variables, formal parameters, the base types of pointer variables, components of structured variables, and function results.
  • By default, objects are not volatile.
  • An object of a structured type that has a volatile component is volatile as a whole. However, the presence of a volatile component does not make other components of the same variable volatile.
  • The presence of the VOLATILE attribute guarantees that operations are performed on scalar objects in an atomic fashion. Because operations on structured objects can require many more instructions, the use of the VOLATILE attribute on an object of a structured type can not produce the expected results, if the data is accessed asynchronously.
  • A volatile variable is structurally compatible only with a formal variable parameter that is volatile. The compiler does not allow a volatile variable to be passed to a nonvolatile formal VAR parameter because the called routine did not guarantee that it could handle volatile parameters.
  • Formal VAR parameters with the VOLATILE attribute can accept both volatile and nonvolatile actual parameters; treating a nonvolatile variable as volatile never produces the wrong answer.
  • A pointer expression whose base type is volatile is assignment compatible only with a pointer variable whose base type is volatile.
  • Two pointer types are structurally compatible only if their base types have identical volatility.
  • On OpenVMS I64 and OpenVMS Alpha systems, the VOLATILE attribute ensures true atomic accesses for bytes, aligned words, aligned longwords, and aligned quadwords. For unaligned words, unaligned longwords, or unaligned quadwords that are marked VOLATILE, the compiler will issue a warning message indicating that the resulting code sequence is not an atomic sequence and contains a timing window where incorrect results can occur if an asychronous thread writes to the unaligned volatile storage.
    See the HP Pascal for OpenVMS User Manual for information on how to enable/disable the message.
    VOLATILE accesses of items larger than 64 bits (strings, entire records, entire arrays, and other such items) have never been atomic in nature and are not flagged by the compiler. The VOLATILE attribute ensures atomic access for all objects 32 bits or less.

Table 10-6 Allowed Combinations of Volatile and Nonvolatile Parameters
Actual Formal Parameter
Parameter VAR VAR [VOLATILE] [VOLATILE]
Volatile No Yes Yes
Nonvolatile Yes Yes Yes

Consider the following example:



VAR
   x : CHAR;
   a : [VOLATILE] RECORD
      CASE BOOLEAN OF
         FALSE : ( i : INTEGER );
         TRUE  : ( c : CHAR );
      END;
{In the executable section:}
a.c := 'A';       {TRUE becomes the current variant}
a.i := 66;        {Assignment makes FALSE the current variant}
x   := a.c;       {TRUE is again the current variant;
                     X is assigned the value 'B', which
                     has an ordinal value of 66}

As the comments in this example show, a reference to one field identifier causes the corresponding variant to become the current variant. In addition, each reference immediately causes the other variant to become undefined. So, when the assignment a.i := 66 is made, the reference to a.i causes FALSE to become the current variant and a.c to become undefined. As a result of the statement x := a.c, the value last assigned to the variant is assigned to x. Ordinarily the compiler could assume that a.c had retained the value 'A', because no further assignments had been made directly to a.c. However, the value of a.c changed unexpectedly through the assignment to a.i. Therefore, unless the record a is declared VOLATILE, the result of the assignment
x := a.c would be undefined because the compiler's legitimate assumptions had been incorrect.

Consider the following example:



PROGRAM Volatility( OUTPUT );
VAR
   Pint : ^[VOLATILE] INTEGER;
   i    : INTEGER;
   j    : [VOLATILE] INTEGER;
   a    : ARRAY[0..10] OF INTEGER;
{In the executable section:}
NEW( Pint );
i     := 0;
j     := 0;
Pint^ := 0;

{Compiler may assume i = 0, makes no assumptions about j}
WRITELN( i, j, Pint^, a[i] );     {Values are 0, 0, 0, a[0] }
Pint  := ADDRESS( j );            {Pint^ now = j}
Pint^ := 1;                       {Therefore j now = 1}

{Compiler may assume i = 0, makes no assumptions about j}
WRITELN( i, j, Pint^, a[i] );     {Values are 0, 1, 1, a[0]}
Pint := ADDRESS( i );             {Causes a warning message
                                    because i is not VOLATILE}
Pint^ := 2;

{Compiler may assume i = 0 and a[I] = a[0],
May make no assumptions about j}
WRITELN( i, j, Pint^, a[i] );  {Actual values are 2, 1, 2, a[2]}

This example assigns values to the variables i and j and to the newly created variable Pint^. The comments show the difference between the assumptions the compiler can legally make about the values of the variables and the values actually contained in the variables. The compiler's assumption about the value of i was incorrect because the value of i changed unexpectedly. The ADDRESS( i ) call caused Pint to point to i (that is, Pint^ and i became the same variable). When Pint^ was assigned the value 2, the variable i also received the value 2. Since i had been initialized to 0 and was not directly referred to in the rest of the program, the compiler assumed that a reference to i at this point would be equivalent to a reference to 0. Likewise, the compiler also assumed that a reference to a[i] would be equivalent to a reference to a[0]. However, when execution ceases, the value of i is 2 and the value of a[i] is the value of a[2].

Depending on the optimizations the compiler made based on the value of i, any operations performed after the unanticipated assignment to i could yield unexpected results. Because j was declared VOLATILE, the compiler did not optimize code based on the value of j. Therefore, any reference to j yields the expected results.

The ADDRESS( i ) call in this program causes a warning message. TheHP Pascal compiler assumes that pointer variables point only to variables in heap-allocated storage and not to statically allocated, nonvolatile variables such as i. So, ADDRESS( i ) in this case differs from the expected usage.

For More Information:

  • On use of VOLATILE with the ASYNCHRONOUS attribute ( Section 10.2.3)
  • On exception handlers (HP Pascal for OpenVMS User Manual)
  • On volatility (HP Pascal for OpenVMS User Manual)

10.2.43 WEAK_EXTERNAL

The WEAK_EXTERNAL attribute specifies that a variable or routine is not critical to the linking operation. To resolve a weak reference, the linker searches only the named input modules. You can specify an identifier with this attribute to indicate the name by which the corresponding object is known to the linker.


                              {identifier        }
         [ WEAK_EXTERNAL [[ ( {'string-literal'  } ) ]] ]
                              {                  }

identifier

Identifier passed to the linker. If you omit the identifier, the name of the variable is used as the name of the common block.

string-literal

Passes the specified string-literal to the linker unmodified.

Compilation units cannot have the EXTERNAL or WEAK_EXTERNAL attribute.

For More Information:

  • On the EXTERNAL attribute ( Section 10.2.15)
  • On linking (HP Pascal for OpenVMS User Manual)

10.2.44 WEAK_GLOBAL

The WEAK_GLOBAL attribute specifies that an object is linked only when it is specifically included in the linking operation. To resolve a weak reference, the linker searches only the named input modules. You can specify an identifier to indicate the name by which the corresponding object is known to the linker.


                            {identifier        }
         [ WEAK_GLOBAL [[ ( {'string-literal'  } ) ]] ]
                            {                  }

identifier

Identifier passed to the linker. If you omit the identifier, the name of the variable is used as the name of the common block.

string-literal

Passes the specified string-literal to the linker unmodified.

For More Information:

  • On the GLOBAL attribute ( Section 10.2.17)
  • On linking (HP Pascal for OpenVMS User Manual)

10.2.45 WORD

The WORD attribute specifies the amount of storage in words to be received by the object.


WORD [[( n )]]

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

For More Information:

10.2.46 WRITEONLY

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

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, objects can be both read and written.
  • A write-only object cannot be used in expressions.
  • A write-only component in an object of a structured type prohibits the object from being read.
  • A write-only actual variable parameter can be passed only to a formal variable parameter that is write-only.
  • A pointer expression whose base type is write-only is assignment compatible only with a pointer variable whose base type is write-only.

Consider the following example:



PROGRAM SAMPLE;
TYPE
   W_Only = [WRITEONLY] INTEGER;
VAR
   Writ_Int : W_Only;
   Norm_Int : INTEGER;

PROCEDURE Try_Access( VAR Write_Param : W_Only );  EXTERNAL;

{In the executable section:}
Writ_Int := SQR( Norm_Int );
Try_Access( Writ_Int );

This example shows legal statements involving write-only variables. The write-only variable Writ_Int is assigned the result of the square root operation, and is then passed as an actual parameter to a write-only formal parameter.

For More Information:

10.3 Attribute Classes

An attribute class can consist of a single attribute or of several attributes with a common characteristic. Table 10-7 lists the classes and their attributes.

Table 10-7 Attribute Classes
Class Attributes Description of Attributes
Alignment ALIGN, ALIGNED, UNALIGNED Indicate whether the object should be aligned on a specific address boundary in memory.
Allocation AT, AUTOMATIC,
COMMON, STATIC,
PSECT
Indicate the form of storage that the object should occupy.
Asynchronous ASYNCHRONOUS Indicates that the routine can be called by an asynchronous event, such as a condition handler.
Check CHECK Indicates error-checking options to be enabled or disabled.
Double
precision
FLOAT Indicates the type of precision to use for objects of type DOUBLE.
Enumeration ENUMERATION_SIZE Indicates the sizes used for enumerated types and Boolean types.
Environment ENVIRONMENT,
PEN_CHECKING_STYLE
Indicate that HP Pascal creates an environment file, which allows compilation units to share data definitions and declarations.
Hidden HIDDEN Indicates exclusion of a declaration or definition from a created environment file.
Ident IDENT Indicates the identification of a compilation unit to be passed to the linker.
Inherit INHERIT Indicates that the compilation unit can use the definitions and declarations specified in the inherited environment file.
Initialize INITIALIZE Indicates that the procedure is to be called before execution of the main program.
Key KEY Indicates key information for a record field that is used when accessing data in an indexed file.
List LIST Indicates that the routine can be called with actual parameter lists of various lengths.
Optimization OPTIMIZE, NOOPTIMIZE Indicate whether HP Pascal should optimize code.
Parameter
passing
CLASS_A, CLASS_NCA,
CLASS_S, IMMEDIATE,
REFERENCE
Indicate the passing mechanism to be used for a parameter.
Position POS Indicates that a record field should be forced to a specific bit position.
Read-only READONLY Indicates that the object can be read but cannot be written to.
Size BIT, BYTE, WORD,
LONG, QUAD,
OCTA
Indicate the amount of storage to be reserved for the object.
Truncate TRUNCATE Indicates that the actual parameter list can be truncated at the position of this attribute in the formal parameter list.
Unbound UNBOUND Indicates that the routine does not access automatic variables outside its scope.
Unsafe UNSAFE Indicates that an object can accept values of any type without type checking.
Value VALUE Indicates that the variable is a reference to an external constant or is the defining point of a global constant.
Visibility LOCAL, EXTERNAL,
GLOBAL,
WEAK_EXTERNAL,
WEAK_GLOBAL
Indicate the ability of an object to be shared by compilation units.
Volatile VOLATILE Indicates that the value of an object can change at unusual points in program execution.
Write-only WRITEONLY Indicates that the object can be written to but cannot be read.

Some attributes are allowed to appear on routine declarations, routine parameters, and compilation units. Table 10-8 lists these attribute classes.

Table 10-8 Attributes on Routines and Compilation Units
Class Program Element
  Routine
Parameter
Routine Compilation
Unit
Allocation No Yes 1 Yes 1
Asynchronous Yes Yes No
Check No Yes Yes
Double precision No No Yes
Enumeration No No Yes
Environment No No Yes
Ident No No Yes
Inherit No No Yes
Initialize No Yes No
List Yes 2 No No
Optimization No Yes Yes
Truncate Yes No No
Unbound Yes Yes No
Visibility No Yes Yes 3

1PSECT is the only allocation attribute allowed.
2Allowed only on EXTERNAL routine definitions.
3EXTERNAL and WEAK_EXTERNAL are not allowed.

Attribute classes are allowed on various data items. Table 10-9 lists the classes that can be applied to various data items.


Previous Next Contents Index