Kednos PL/I for OpenVMS
Alphatm
Release Notes for Version 4.5 and Runtime Library
Version 4.4H
14 Overview of New Features in Version 4.0
DEC PL/I Version 4.0 is based on VAX PL/I Version 3.5. DEC PL/I Version
4.0 also includes support for IEEE floating-point data. Version 4.0A
also contains the new features of Version 4.0.
14.1 Overview of Language Support
DEC PL/I Version 4.0 is primarily a VAX PL/I Version 3.5 compatibility
release. The following sections contain information on support or lack
of support for language elements.
14.2 DEBUG Support
DEC PL/I Version 4.0 does not contain full debug support for the
following PL/I language data types:
- PL/I unaligned bit-string array variables with run-time sizes and
PL/I parameter unaligned bit-string array variables with run-time
sizes.
The following sample program shows an unaligned bit-string
array variable:
p : procedure options (main);
call p1 (5);
end;
p1 : procedure (size_ch);
dcl (size_ch) fixed binary;
dcl rtb1(size_ch) bit(5);
dcl rtb2(size_ch,size_ch) bit(5);
end;
|
In addition, on OpenVMS AXP you cannot correctly examine or
deposit to any PL/I unaligned bit-string array variable of unknown size.
- PL/I picture variable data type, as the following program fragment
shows:
declare p2 picture <picture-specification>;
|
- PL/I varying character variables with run-time sizes, as the
following sample program shows:
p : procedure options (main);
call p1 (5);
end;
p1 : procedure (size_chv);
dcl (size_chv) fixed binary;
dcl strv1 character (size_chv) varying init('sksks');
strv1 = 'abcde';
end;
|
In addition, on OpenVMS AXP if a string has run-time bounds the
debugger examines and deposits to the variable as if it is a nonvarying
string. The work around is to use the debug command "EXAMINE/ASCIW"
- Label array variables.
- Label constants.
- Entry variables and label variables.
- Structure parameter variables of unknown size, specifically PL/I
structure parameters declared with star extents or members with unknown
size, are not fully supported.
- PL/I external, controlled, defined, and based variables; for
example, you cannot examine the externally declared PL/I based variable
pli_based_nofp shown in the following sample program:
dcl pli_globaldef fixed binary(31) globaldef;
dcl pli_based_nofp fixed binary(31) based(addr(pli_globaldef));
p : procedure options (main);
end;
|
- Differences in behavior between VAX PL/I and DEC PL/I that involve
unreferenced static variables, unreferenced globaldef variables,
unreferenced internal static variables, and unreferenced automatic
variables.
- Referenced PL/I %REPLACE floating-point constants.
- PL/I REFER structures across all data types.
- Depositing to PL/I bit-string variables using the B format:
DBG> DEPOSIT BIT = '111'B
|
The workaround is to deposit without using the B, (i.e. DEPOSIT
BIT = '111')
- Referenced PL/I structures declared as globalref. No debugger
information is output for the structure members.
- Position attribute for PL/I bit-string variables.
14.3 Differences in VAX PL/I and DEC PL/I Support for Floating-Point Data Types
DEC PL/I Version 4.0 supports five floating-point data types: F, D, G,
IEEE S, and IEEE T float. VAX PL/I supports four floating-point data
types: F, D, G and H. When you declare a float binary object with a
precision greater than 53 (which requires the H floating-point data
type), the DEC PL/I compiler supplies a precision of 53 (the maximum
value of the G floating-point data type). When you declare a float
decimal object with a precision greater than 15 (which requires the H
floating-point data type) the DEC PL/I compiler supplies a precision of
15 (the maximum value of the G floating-point data type).
- DEC PL/I may produce truncated results when higher precision values
are specified.
The following PL/I program shows the output from
DEC PL/I when precision values exceeding the limits are specified:
p : procedure options (main);
dcl h float binary (113);
dcl d float decimal (34);
end;
|
The output received from the DEC PL/I compiler for this program is
as follows:
declare d float decimal (34);
........^
%PLIG-W-FLTDPREC, The precision specified for "D" exceeds
the implementation's limit of FLOAT DECIMAL(15). The
maximum precision of 15 has been supplied.
at line number 3 in file tdisk:[tdir]t.pli;1
declare h float binary (113);
........^
%PLIG-W-FLTBPREC, The precision specified for "H" exceeds
the implementation's limit of FLOAT BINARY(53). The
maximum precision of 53 has been supplied.
at line number 2 in file tdisk:[tdir]t.pli;1
%PLIG-I-SUMMARY, Completed with 0 errors, 2 warnings, and
0 informational messages.
|
- Before VAX PL/I Version 3.5, certain G and H floating values could
improperly be truncated when they were converted to either a
fixed-decimal or pictured datatype.
Even when the PLI command line
does not include the /G_FLOAT qualifier and the program does not
include floating-point variables large enough to require H float, the
VAX PL/I Version 3.5 compiler can generate code that uses H floating
data when intermediate calculations require higher precision in order
to produce correct results.
OpenVMS AXP PL/I Version 4.0A does not
support a floating-point data type with a precision higher than 53, the
maximum value of the G floating-point data type. Therefore, certain
conversion operations performed by DEC PL/I may produce results that
are truncated in comparison to the results produced by VAX PL/I.
14.4 Support for Other Language Elements
In DEC PL/I Version 4.0A, the format of the ONARGSLIST built-in
function is identical to that of VAX PL/I. However, the data structure
pointed to by the mechanism array pointer is different.
15 Overview of Changes from VAX PL/I
In addition to the new features outlined above, DEC PL/I Version 4.0
contains the following changes from the VAX PL/I Version 3.5 product.
- Changes to correct VAX PL/I Version 3.5 errors
A secondary
objective of this release is correction of VAX PL/I Version 3.5 errors.
A number of problems with Version 3.5 have been corrected. Some of
these were documented in the Version 3.5 release notes, while others
were discovered after the release of Version 3.5.
- Changes in virtual memory requirements
The virtual memory
requirements for DEC PL/I may be extensive depending to the type of
PL/I language constructs that you use. Processing the PUT and GET
statements, BEGIN blocks and PROCEDURE blocks with the DEC PL/I
compiler tend to require more virtual memory than the same operation
would if you were using the VAX PL/I compiler.
Heavy usage of
these constructs in your programs may exhaust your user limits for
virtual memory. The typical compiler errors that you receive are:
%PLIG-F-TEXT, Compiler abort - virtual memory limits exceeded.
%SYSTEM-F-ABORT, abort
%LIB-F-INSVIRMEM, insufficient virtual memory
|
You can recover by increasing your user page-file quota
(PGFLQUOTA). See the Kednos PL/I for OpenVMS Alpha Installation Guide or the OpenVMS System Manager's Manual
for more information on increasing your user page-file quota.
- Changes in behavior for calls to bound procedures
With VAX
PL/I, nested procedures can be called by other routines using the PL/I
language's entry variable. However, in order to successfully reach
these bound-procedure routines and ensure proper execution of
uplevel-referenced variables within the bound procedures, the user must
keep the parent invocation of the bound procedure active.
This
assures that the stack references to uplevel variables within the bound
procedure to the parent's stack, which contained the uplevel-referenced
variables, are still valid.
With DEC PL/I the same situation still
exists; however, you may experience different behavior between VAX PL/I
and DEC PL/I if you do not keep the parent invocation active. This is
due to the fact that bound procedures are not created in the same way
by the two compilers.
DEC PL/I creates the bound procedure values
on the stack of the parent of the bound procedure. The user program may
produce an access violation or may exhibit other undefined behavior
when the parent invocation of the bound procedure is not kept active.
Because the stack of the parent has been destroyed, the bound procedure
code found on the parent stack may also have been destroyed or
corrupted, and the user may not be able to reach the bound procedure.
With VAX PL/I you may receive the same undefined behavior. Cases
may exist in which you are able to reach the bound procedure; however,
you may still receive errors in results from the uplevel-referenced
variables within the bound procedure. This is because the bound
procedure code on the parents stack may have been corrupted.
The
following example shows behavior where the bound procedure entry6a
cannot be reached by DEC PL/I, because the parent procedure, entry6,
has exited and its stack is free to be recovered and used by other
procedures. Therefore, the bound procedure code has been destroyed.
Note that this programs also fails with VAX PL/I. However, it
fails after having reached the bound procedure entry6a and while trying
to access the uplevel-referenced variables from the parent, entry6.
Example of Bound Procedure Failure Behavior If Parent Bound
Procedure is Inactive
program: proc options(main);
program: proc options(main);
dcl (ent2) entry variable;
dcl fnc entry returns(entry) variable;
dcl evar char (25) var init(' ');
fnc=entry6;
ent2=fnc();
call destroy_stack();
call ent2;
put skip list('Evar is =>',evar);
entry6: proc returns (entry);
return(entry6a);
entry6a: proc;
evar=evar||'entry6a*';
return;
end entry6a;
end entry6;
destroy_stack: proc;
/* Declare enough space to destroy previous
* stack values before this call.
*/
dcl temp_space char(1000);
temp_space = 'hello';
end;
end program;
|
- Changes in behavior for overlapping static storage initialization
In VAX PL/I and DEC PL/I, overlapping initialization of static
storage is not supported. When VAX PL/I finds an overlapping static
initialization, the compiler uses the value of the last found
initialization as the value for the static variable.
In DEC PL/I
you cannot depend on the value of the last found initialization being
assigned to the static variable. This behavior may cause a change in
behavior for PL/I external variable initializations.
If a PL/I
external variable is declared with the attributes EXTERNAL STATIC
INITIAL, all blocks that declare the variable MUST be initialized with
the same value.
Because VAX PL/I allowed overlapping static
storage initialization, you could specify different initial values for
the SAME external variable within containing blocks. The last initial
value encountered by the VAX PL/I compiler was the value of the
external variable.
In DEC PL/I this rule is more strictly
enforced: if the user specifies an initial value in the declaration of
a PL/I external variable, the same initial value declaration must be
specified at each occurrence of the declaration of the external
variable in all blocks that declare the external variable. Failure to
do so can cause unpredictable results. The following examples
illustrate correct and incorrect declarations:
Correct Declaration of an External Variable
Initialization
program: proc options(main);
dcl test fixed external initial(5);
p:proc;
dcl test external initial(5);
/* The value of this variable should be 5. */
put skip list ('The value of test is =>',test);
end;
end;
|
Incorrect Declaration of an External Variable
Initialization
program: proc options(main);
/* The initialization MUST be the same
* for all declarations of the external
* variable.
*/
dcl test fixed external initial(5);
dcl test1 fixed external initial(5);
dcl test2 fixed external;
p:proc;
/* The initialization MUST be the same
* for all declarations of the external
* variable.
*/
dcl test external initial(6);
dcl test1 external;
dcl test2 external initial(6);
/* The value of these variables is unpredictable.
*/
put skip list ('The value of test is =>',test);
put skip list ('The value of test1 is =>',test1);
put skip list ('The value of test2 is =>',test2);
end;
end;
|
Note
As no guarantee exists as to which occurrence of the external variable
the DEC PL/I compiler processes first, each occurrence of the variable
must contain the same initial value.
|
- Changes in behavior for the SUBSTR built-in function
In PL/I,
the SUBSTR function is defined only when the position attribute (the
integer expression that indicates the position of the first bit or
character in the substring) is greater than or equal to 1.
If the
position attribute is less than 1 (that is, the SUBSTR BIF is
undefined), you may observe different results with DEC PL/I than with
VAX PL/I.
- Changes in underflow detection behavior for DEC PL/I
The VAX
PL/I compiler outputs underflow detection code, whereas the DEC PL/I
compiler does not.
- Changes for null statements and label behavior in DEC PL/I
VAX
PL/I does not compare the multiple labels of many succeeding
combinations of labels and null statements so that they have the same
address. However, DEC PL/I optimizes these label-null statement
sequences and compares the multiple labels so that they result in the
same address. The following example illustrates this difference:
X67: PROC options(main);
A:; /* Null statement. */
B:; /* Null statement. */
C:; /* Null statement. */
IF A=C THEN
PUT LIST('NULL STATEMENT LABELS COMPARE EQUAL FOR DEC PL/I');
ELSE
PUT LIST('NULL STATEMENT LABELS COMPARE NOT EQUAL FOR VAX PL/I');
D:
IF C=D THEN
PUT LIST('ERROR THESE LABELS SHOULD NEVER COMPARE EQUAL');
END;
|
- In DEC PL/I you can continue when a GOTO statement with the
OTHERWISE option is used to go to an undefined label array element
within a BEGIN-END block. VAX PL/I does not support this function. The
following example works with DEC PL/I but not VAX PL/I:
program: procedure options(main);
dcl i fixed binary(31,0);
begin;
i = 2;
goto part(i) otherwise;
put skip list('At continue !!');
end;
part(1):
end program;
|
- Run-time exception handling is more consistent when processing
formats of GET EDITs and PUT EDITs in DEC PL/I than it is in VAX PL/I.
If DEC PL/I encounters an exception when processing a format such as
PLI$_INVFMTPARM, a signal is raised. If the exception is handled, then
processing continues with the next format item regardless of the nature
of the signal and the format item that was being processed when the
exception was detected. This is not always the case with VAX PL/I.
This holds true for conversion errors as well. With VAX PL/I, some
conversions with GET EDIT would raise the CONVERSION condition while
others would raise the ERROR condition (with ONCODE()=PLI$_CNVERR). DEC
PL/I uniformly raises CONVERSION when data cannot be converted. The
following example demonstrates this difference.
cnverr: proc options (main);
%include $plidef;
declare
srcstring character(10) initial('4 4445'),
temp fixed bin(31);
on error begin;
if oncode() = pli$_cnverr then
put skip list('VAX PL/I detects CNVERR (not restartable)');
if oncode() = pli$_oncnvpos then
put skip list('DEC PL/I detects ONCNVPOS (restartable)');
goto done;
end;
get string (srcstring) edit (temp) (b3(6));
done:
end cnverr;
|
- Nonlocal returns work properly under DEC PL/I. A nonlocal return
is a RETURN statement that is lexically nested between any number of
BEGIN/END pairs; for example:
nested_proc : proc returns (fixed);
begin;
begin;
begin;
begin;
begin;
return (5);
end;
put skip list ('shouldnt be here 1');
end;
put skip list ('shouldnt be here 2');
end;
put skip list ('shouldnt be here 3');
end;
put skip list ('shouldnt be here 4');
end;
put skip list ('shouldnt be here 5');
end;
nested_proc2 : proc returns (float);
begin;
begin;
begin;
begin;
begin;
return (5.1);
end;
put skip list ('shouldnt be here 1');
end;
put skip list ('shouldnt be here 2');
end;
put skip list ('shouldnt be here 3');
end;
put skip list ('shouldnt be here 4');
end;
put skip list ('shouldnt be here 5');
end;
program: proc options(main);
dcl result1 fixed;
dcl result2 float;
result1 = nested_proc();
result2 = nested_proc2();
put skip list (result1);
put skip list (result2);
end;
|
Two special considerations should be observed for nonlocal returns
from OPTIONS(MAIN) procedures. First, an ON unit declared in the scope
of one of the BEGIN/END pairs for FINISH is given a chance to execute.
Second, an ON unit declared in the scope of one of the BEGIN/END pairs
for VAXCONDITION(SS$_UNWIND) is NOT be given a chance to execute with
the above construct.
- When a main program (for example, pname :
procedure(options(main))) terminates abnormally due to an unhandled
exception, DEC PL/I closes all open files before turning control over
to the OpenVMS last-chance condition handler (the utility that prints
the error and traceback).
This means that I/O that was being held
in a buffer is allowed to reach its destination before the error dump
appears on the screen. This is not the case with VAX PL/I, in which I/O
held in a buffer is not allowed to reach its destination before the
error dump appears on the screen.
- Differences in exception handling between OpenVMS AXP and OpenVMS
VAX
Since machine instructions on Alpha AXP(tm) differ from those
of the VAX, any exception handler written to handle VAX hardware
exceptions should be examined to ensure that it handles Alpha AXP
hardware exceptions similarly. For example, consider a case in which an
exception handler has been written to handle an access violation. You
may expect different behavior upon normal completion of the handler. In
this case the handler should always perform a nonlocal GOTO to exit the
handler so that program execution continues in a predictable way.
Note also that exceptions on the Alpha AXP hardware are imprecise and
therefore are not always restartable. Digital recommends using a
non-local goto to achieve consistent behavior across both PL/I
platforms.
- Fixed-decimal precision differences between DEC PL/I and VAX PL/I
The precision specified for a PL/I fixed-decimal data type must be
in the range of 1 to 31 for DEC PL/I. VAX PL/I allows a fixed-point
decimal variable to be declared with a precision of zero and also
allows built-in functions to specify a fixed-decimal precision of zero.
DEC PL/I does not allow zero to be used in either of these situations
and issues an error "FIXDPRECZERO" when the precision specified for a
fixed decimal is zero.
- Differences in behavior between OpenVMS VAX and OpenVMS AXP
architectures regarding PL/I overflow conditions
In general, any
PL/I operation that overflows on OpenVMS VAX also overflows on OpenVMS
AXP. Since the Alpha AXP hardware does not include support for packed
decimal instructions that correspond to the PL/I FIXED DECIMAL
datatype, data items of this type are handled on OpenVMS AXP by
run-time calls, to either the DEC PL/I Run-Time Library routines or
system Object Time 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. Many emulation operations generate an overflow.
Therefore, DEC PL/I guarantees at least one overflow on OpenVMS AXP for
every overflow on OpenVMS VAX per PL/I statement. DEC PL/I cannot
guarantee that the resulting behavior or value produced by a PL/I
statement that produces an overflow condition is the same value or
behavior as it is on VAX PL/I.
The following example illustrates a
difference in overflow detection between VAX PL/I and DEC PL/I:
23 1 fixb30 = fixd21;
0125 mulp #10,PLI$B_PAC_2_POWER_30,#31,-60(fp),#31,-96(fp)
0132 ashp #-21,#31,-96(fp),#0,#31,-112(fp)
013C cvtpl #31,-112(fp),r4
0141 movl r4,-80(fp)
|
The difference occurs when a PL/I fixed decimal data item with a
precision of 31 and a scale factor of 21 [FIXED DECIMAL(31,21)] is
converted to a PL/I fixed binary data item with a precision 31 and a
scale factor of 30 [FIXED BINARY(31,30)]. On OpenVMS VAX this overflow
situation results in two overflow conditions being raised. On OpenVMS
AXP this situation results in one overflow condition being raised.
Note that all VAX PL/I cases of overflow are detected on OpenVMS AXP in
the program. In the example, DEC PL/I detects one overflow for the two
overflows reported by VAX PL/I. This difference is due to a difference
in the instruction set between and AXP.
The example illustrates
two occurrences of this situation. In each case the fixed decimal item
is converted to fixed binary item by a series of three steps, as
follows:
- Multiplies the fixed decimal(31,21) item by the decimal
representation of 2**30.
- Shifts the fixed decimal (31,51) created by step 1 to the right by
21.
- Converts the fixed decimal (31,30) created by step 2 to a fixed
binary item (31,30).
The OpenVMS VAX macro instructions output by VAX PL/I to perform
this conversion are as follows:
23 1 fixb30 = fixd21;
0125 mulp #10,PLI$B_PAC_2_POWER_30,#31,-60(fp),#31,-96(fp)
0132 ashp #-21,#31,-96(fp),#0,#31,-112(fp)
013C cvtpl #31,-112(fp),r4
0141 movl r4,-80(fp)
|
In example, during the execution of the OpenVMS VAX mulp
instruction, and during the OpenVMS VAX cvtpl instruction,
overflows occur. The OpenVMS AXP instruction set does not contain
decimal instructions. Therefore, OpenVMS VAX emulates decimal
instructions by means of a series of OpenVMS AXP instructions and OTS
calls. During the instructions to emulate the OpenVMS VAX mulp
instruction, an overflow is correctly detected. During the instructions
to convert packed-decimal data to integer data, an overflow is not
detected.
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
multiplication that caused the overflow is undefined. When it is used
in an expression, no guarantee exists that an overflow will be raised
again. This happens when the result of the overflow is shifted to the
right and then converted from decimal to integer. 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 between OpenVMS VAX
and OpenVMS AXP instructions, this situation cannot be prevented.
In general, on a per-statement basis DEC PL/I detects overflow, but the
number of overflows it detects per statement is not guaranteed to be
the same on OpenVMS VAX and OpenVMS AXP. The following complete example
illustrates 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;
|