Differences in behavior between OpenVMS VAX and OpenVMS Alpha
architectures regarding PL/I error conditions
In general, any PL/I
operation that overflows on OpenVMS VAX systems will also overflow
with Kednos PL/I for OpenVMS Alpha on OpenVMS Alpha systems. However, the Alpha
hardware does not include support for packed decimal instructions that
correspond to the PL/I fixed decimal data type; data items of this type
are handled on OpenVMS Alpha systems through run-time calls, either to
Kednos PL/I for OpenVMS Alpha run-time library routines or to system OTS routines.
These emulation routines perform many operations to compute the result
of a fixed decimal operation, which in most cases can be done with a
single VAX instruction. Any one of these many emulation
operations can and will generate an overflow.
Therefore,
Kednos PL/I for OpenVMS Alpha can guarantee at least one overflow only on OpenVMS Alpha
systems for every overflow on OpenVMS VAX systems per PL/I statement.
Kednos PL/I for OpenVMS Alpha cannot guarantee that the resulting behavior or value
produced by a PL/I statement that produces an overflow condition will
be the same value or behavior as it was on Kednos PL/I for OpenVMS VAX.
The
following PL/I example shows the difference in overflow detection
between Kednos PL/I for OpenVMS VAX and Kednos PL/I for OpenVMS Alpha. This difference occurs when a
PL/I fixed-decimal item with precision of 31 and scale factor of 21
[fixed decimal(31,21)] is converted to a PL/I fixed binary item with
precision 31 and scale of 30 [fixed binary(31,30)]. On OpenVMS VAX
systems this overflow situation results in two overflow conditions
being raised. On OpenVMS Alpha systems this situation results in one
overflow condition being raised.
Note that all Kednos PL/I for OpenVMS VAX cases
of overflow are detected on OpenVMS Alpha systems here. However, in
this case Kednos PL/I for OpenVMS Alpha detects one overflow for the two overflows
reported by Kednos PL/I for OpenVMS VAX. This difference is due to a difference in
the instruction set between OpenVMS VAX and OpenVMS Alpha systems and
a further explanation is detailed below.
The selected program
fragment contained here shows two examples of this situation. In each
case the fixed-decimal item is converted to a fixed-binary item by a
series of three steps.
- Multiplies the fixed decimal(31,21) item by the decimal
representation of 2**30.
- Shifts the fixed decimal (31,51) created by step 1 right by 21.
- Converts the fixed decimal (31,30) created by step 2 to a fixed
binary (31,30).
The VAX macro instructions output by Kednos PL/I for OpenVMS VAX to
perform this conversion are:
23 1 fixb30 = fixd21;
A0 AD 1F C4 AD 1F 00000000* EF 0A 25 0125 mulp #10,PLI$B_PAC_2_POWER_30,#31,-60(fp),#31,-96(fp)
90 AD 1F 00 A0 AD 1F EB 8F F8 0132 ashp #-21,#31,-96(fp),#0,#31,-112(fp)
54 90 AD 1F 36 013C cvtpl #31,-112(fp),r4
B0 AD 54 D0 0141 movl r4,-80(fp)
|
In this example fragment, overflows are detected during the
VAX mulp instruction which causes an overflow to
occur and during the VAX cvtpl instruction. The
OpenVMS Alpha instruction set does not contain decimal instructions, so
the OpenVMS VAX decimal instructions are emulated by a series of
OpenVMS Alpha instructions and OTS calls. During the instructions
generated on by OpenVMS Alpha systems by Kednos PL/I for OpenVMS Alpha to emulate the
OpenVMS VAX mulp instruction, an overflow is correctly
detected. During the instructions to convert packed decimal to integer,
an overflow is not detected, however.
Note that after a
fixed-overflow condition has been raised, the value resulting from an
operation that causes this condition is undefined. In this case, the
value from the result of the multiply that caused an overflow is
undefined. Therefore, when it is used in the expression no guarantee
exists that an overflow will be raised again. This is what is happening
when the result of the overflow is shifted right and then converted
from decimal to integer. Therefore, in this case it is reasonable to
expect a difference in the number of overflows detected from one PL/I
statement.
Due to the difference in OpenVMS VAX and
OpenVMS Alpha systems instructions, we can not prevent this situation
from occurring. If you notice a situation during a conversion in which
you receive one overflow on OpenVMS Alpha systems but two on
OpenVMS VAX systems this is likely to be the reason.
In general,
on a per-statement basis Kednos PL/I for OpenVMS Alpha can be expected to detect
overflow, but the number of overflows detected per statement cannot be
guaranteed to be the same on OpenVMS VAX and OpenVMS Alpha systems.
The following complete example shows the difference:
program: procedure options(main);
dcl fixb30 fixed bin(31,30);
dcl fixd18 fixed decimal(31,18);
dcl fixd21 fixed decimal(31,21);
dcl fixd22 fixed decimal(31,22);
dcl fixd24 fixed decimal(31,24);
on fixedoverflow begin;
put skip list('fixed overflow occurred');
end;
fixd18 = 18.36;
fixd22 = 22.40;
fixd21 = fixd18+fixd22;
fixb30 = fixd21;
fixd18 = 18.42;
fixd24 = 24.58;
fixd21 = fixd24+fixd18;
fixb30 = fixd21;
end;
|
D.3 Implicit Conversions
The Kednos PL/I compilers issue warning-level messages when they
perform implicit conversions between arithmetic and string data types
and between bit-string and character-string data types. They issue
these messages for all such conversions, not just those excluded by the
PL/I General-Purpose Subset.
You can avoid the messages by compiling your programs with the
/NOWARNINGS qualifier. Otherwise, you can edit your program, locate the
occurrences of implied conversions, and change them to explicit
conversions, as follows:
- Arithmetic to character-string-use the CHARACTER built-in function.
- Arithmetic to bit-string-use the BIT built-in function.1
- Bit-string to arithmetic-use the BINARY built-in function.
- Bit-string to character string-use the CHARACTER built-in function.
- Character-string to arithmetic-use the BINARY, DECIMAL, FIXED, or
FLOAT built-in function, according to the target data type.
- Character-string to bit string-use the BIT built-in function.
Note
1 This conversion is based on the way
bit strings are printed by PUT LIST (the first bit of the string is the
high-order bit if the printed string is viewed as a binary integer)
rather than being based on the internal representation (the first bit
of the string is then in the low-order digit position in memory).
|
D.4 Printing a Hexadecimal Memory Dump
Dump printing routines written for other hardware architectures are not
transportable to OpenVMS VAX and OpenVMS Alpha systems. Because the
order in which bits are stored on OpenVMS machines is reversed on
some other machines, these routines must be entirely rewritten. The
program HEXDUMP that follows shows one technique for outputting the
contents of memory in hexadecimal:
/*
This procedure illustrates the dumping of memory in
hexadecimal. The output format is consistent with other
OpenVMS VAX or OpenVMS Alpha memory dump utilities.
*/
HEXDUMP: PROCEDURE OPTIONS(MAIN);
DECLARE DUMP_LOCATION POINTER;
DECLARE (I,J) FIXED BINARY(31);
/* declare and initialize fake memory to dump */
DECLARE MEMORY(0:255) FIXED BINARY(7);
DO I = 0 TO 127;
MEMORY(I) = I;
MEMORY(I + 128) = I - 128;
END;
/* dump the pseudomemory on the user's terminal */
DO I = 0 TO 255 BY 16;
PUT SKIP;
DO J = 12 TO 0 BY -4;
DUMP_LOCATION = ADDR(MEMORY(I+J));
CALL OUTPUT_HEX(DUMP_LOCATION);
END;
PUT EDIT(' ')(A(1));
CALL OUTPUT_HEX(ADDR(I));
END;
STOP;
/* subroutine to output a hexadecimal longword */
OUTPUT_HEX: PROCEDURE(ADDRESS);
DECLARE ADDRESS POINTER;
DECLARE F FIXED BIN(31) BASED(ADDRESS);
PUT EDIT(REVERSE(UNSPEC(F))) (B4(8));
END OUTPUT_HEX;
END HEXDUMP;
|
Appendix E
Language Summary
This appendix briefly describes PL/I statements, attributes,
expressions, data conversions, built-in functions, pseudovariables, and
built-in subroutines.
E.1 Statements
%activate-statement
%
element
,...;
allocate-statement
allocate-item,...;
allocate-item:
variable-reference [SET(locator-reference)][IN(area-reference)]
|
%assignment-statement
assignment-statement
begin-statement
call-statement
CALL entry-name [(argument,...)];
|
close-statement
- CLOSE FILE(file-reference) [ENVIRONMENT(option,...)]
- [,FILE(file-reference) [ENVIRONMENT(option,...)]]...
%deactivate-statement
%
element,...;
element:
- identifier
- (identifier,...)
%declare-statement
%
element
,...;
element:
- identifier
- (identifier,...)
declare-statement
[level] declaration [,[level] declaration,...];
declaration:
declaration-item:
- identifier
- (declaration-item,...)
[(bound-pair,...)] [attribute...]
delete-statement
DELETE FILE(file-reference) [KEY (expression)][OPTIONS(option,...)]
|
%dictionary-statement
%do-statement
do-statement
DO
- [reference=expression]
- [TO expression [BY expression]]
- [REPEAT expression]
- [WHILE(expression)]
- [UNTIL(expression)];
%end-statement
end-statement
entry-statement
- entry-name: ENTRY [ (parameter,...) ]
-
- [ RETURNS (returns-descriptor) ];
%error-statement
%ERROR preprocessor-expression;
|
%fatal-statement
%FATAL preprocessor-expression;
|
format-statement
label:
FORMAT (format-specification,...);
|
free-statement
FREE variable-reference [IN area-reference],...;
|
get-statement
GET EDIT (input-target,...)(format-specification,...)
- FILE(file-reference)
- [SKIP[(expression)]]
- [OPTIONS(option,...)]
- STRING(expression)
;
GET LIST (input-target,...)
- FILE(file-reference)
- [SKIP[(expression)]]
- [OPTIONS(option,...)]
- STRING(expression)
;
GET [FILE(file-reference)] SKIP [(expression)];
%goto-statement
goto-statement
label-reference ;
%if-statement
%IF test-expression %THEN action [%ELSE action];
|
if-statement
IF test-expression THEN action [ELSE action];
|
%include-statement
%INCLUDE
- 'file-spec'
- module-name
- 'library-name(module-name)'
;
%inform-statement
%INFORM preprocessor-expression;
|
leave-statement
%[no]list-statement
%[NO]LIST;
%[NO]LIST_ALL;
%[NO]LIST_DICTIONARY;
%[NO]LIST_INCLUDE;
%[NO]LIST_MACHINE;
%[NO]LIST_SOURCE;
%null-statement
%;
null-statement
;
on-statement
ON condition-name,...[SNAP]
open-statement
- OPEN FILE(file-reference) [file-description-attribute ...]
- [,FILE(file-reference) [file-description-attribute ...]]...
%page-statement
%procedure-statement
- %label:
[(parameter-identifier,...)][STATEMENT]
- RETURNS (
);
.
.
.
- [%]RETURN (preprocessor-expression);
.
.
.
- [%]END.
procedure-statement
entry-name:
[ (parameter,...) ]
- [ OPTIONS (option,...) ]
-
- [ RETURNS (value-descriptor) ];
put-statement
PUT EDIT (output-source,...) (format-specification,...)
- FILE(file-reference)
- [PAGE]
- [LINE(expression)]
- [SKIP[(expression)]]
- [OPTIONS(option)]
- STRING(reference)
;
PUT [FILE(file-reference)] LINE(expression);
PUT LIST (output-source,...)
- FILE(file-reference)
- [PAGE]
- [LINE(expression)]
- [SKIP[(expression)]]
- [OPTIONS(option)]
- STRING(reference)
;
PUT [ FILE(file-reference)] PAGE;
PUT [ FILE(file-reference)] SKIP [(expression)];
read-statement
- READ FILE (file-reference)
-
- INTO (variable-reference)
- SET (pointer-variable)
-
- KEY (expression)
- KEYTO (variable-reference)
- [ OPTIONS (option,...) ];
%replace-statement
%REPLACE identifier BY constant-value;
|
%return-statement
[%]RETURN (preprocessor-expression);
|
return-statement
RETURN [ (return-value) ];
|
revert-statement
REVERT condition-name,...;
|
rewrite-statement
- REWRITE FILE (file-reference)
- [ FROM (variable-reference) [ KEY (expression) ]]
- [ OPTIONS (option,...) ];
%sbttl-statement
%SBTTL preprocessor-expression
|
select-statement
- SELECT [(select-expression)];
- [WHEN [ANY|ALL] (expression,...) [action];]...
- [{OTHERWISE|OTHER} [action];]
- END;
signal-statement
stop-statement
%title-statement
%TITLE preprocessor-expression
|
%warn-statement
%WARN preprocessor-expression;
|
write-statement
- WRITE FILE(file-reference) FROM (variable-reference)
- [ KEYFROM (expression) ]
- [ OPTIONS (option,...) ];
E.2 Attributes
Computational Data Type Attributes
The following attributes define arithmetic and string data:
- CHARACTER
- BIT
-
- [ [PRECISION] (precision
- [,scale-factor]) ]
- PICTURE 'picture'
These attributes can be specified for all elements of an array and for
individual members of a structure.
Noncomputational Data Type Attributes
The following attributes apply to program data that is not used for
computation:
- AREA
- CONDITION
- ENTRY [VARIABLE]
- FILE [VARIABLE]
- LABEL [VARIABLE]
- OFFSET
- POINTER
Storage Class and Scope Attributes
The following attributes control the allocation and use of storage for
a data variable and define the scope of the variable:
- AUTOMATIC [INITIAL(initial-element,...)]
- BASED [(pointer-reference)][INITIAL(initial-element,...)]
- CONTROLLED [INITIAL(initial-element,...)]
- DEFINED(variable-reference) [POSITION(expression)]
- STATIC [READONLY] [INITIAL(initial-element,...)]
- PARAMETER
- INTERNAL
- EXTERNAL
- GLOBALDEF [(psect-name)]
- GLOBALREF
Member Attributes
The following attributes can be applied to the major or minor members
of a structure:
- LIKE
- MEMBER
- REFER
- STRUCTURE
- TYPE
- UNION
File Description Attributes
The following attributes can be applied to file constants and used in
OPEN statements:
- ENVIRONMENT(option,...)
- INPUT
- OUTPUT [PRINT]
- UPDATE
-
Entry Name Attributes
The following attributes can be applied to identifiers of entry points:
- ENTRY [VARIABLE] [OPTIONS (VARIABLE)]
- [RETURNS (returns-descriptor)]
- BUILTIN
Non-Data Type Attributes
The following attributes can be applied to data declarations:
- ALIGNED
- DIMENSION
- UNALIGNED