PL/I Reference Manual	13.7	List of Built-in Functions

LOCK

Category:	miscellaneous
Format:	LOCK(F,I)
Parameter:	F is a file constant or variable that must be opened
	in Shared mode. I is a FIXED BINARY(15) integer that
	gives the record number relative to the record size
	specified in the ENVIRONMENT option.
Result:	Returns a one-bit if the operation is successful or a
	zero-bit if unsuccessful. Locks the record
	specified by I so that no other user can lock or
	access it. The record remains locked until unlocked
	with the UNLOCK function, or the program terminates.
Result Type:	BIT(l)
Remark:	Only available if supported by operating system.

LOG

Category:	Mathematical
Format:	LOG(X)
Parameter:	X is an arithmetic expression, X > 0.
Result:	Returns the natural logarithm of X.
Result type:	FLOAT BINARY
Algorithm:	Chebyshev polynomial approximation
Error
Condition:	If X <= 0, the run-time system signals the ERROR(3)
	condition.
Examples:	LOG(10.0) returns 2.3025850E+00
	LOG(10.00000) returns 2.302585124969482E+000
		13-20
PL/I Reference Manual	13.7		List of Built-in Functions

LOG2

Category:		Mathematical
Format:	LOG2(X)
Parameter:		X is an arithmetic expression, X > 0.
Result:	Returns the logarithm of X to the base 2.
Result type:		FLOAT BINARY
Algorithm:		LOG2(X) equals LOG(X)/LOG(2)
Error
Condition:		If X <= 0, the run-time system signals the ERROR(3)
	condition.
Examples:		LOG2(10.0) returns 3.3219270E+00
	LOG2(10.00000) returns 3.321927785873412E+000
		LOGIO

Category:		Mathemetical
Format:	LOG10(X)
Parameter:		X is an arithmetic expression, X > 0.
Result:	Returns the logarithm of X to the base 10.
Result type:		FLOAT BINARY
Algorithm:		LOG10(X) equals LOG(X)/LOG(10)
Error
Condition:		If X < 0, the run-time system signals the ERROR(3)
	condition.
Examples:		LOG10(125.0) returns 2.0969100E+00
	LOG10(125.00000) returns 2.096910013008051E+000
		13-21
PL/I Reference Manual	13.7	List of Built-in Functions

MAX

Category:	Arithmetic
Format:	MAX(X,Y)

Parameters:	X and Y are arithmetic expressions.

Result:	Returns the larger value of X and Y.
Algorithm:	If X >= Y then return X, otherwise return Y.

Result type:	The common arithmetic type of X and Y.

Examples:	MAX(234,64) returns 234
	MAX(3.77e5,9.856e3) returns 3.7700E+05

MIN

Category:	Arithmetic
Format:	MIN(X,Y)

Parameters:	X and Y are arithmetic expressions.

Result:	Returns the smaller value of X and Y.
Algorithm:	If X<= Y, then return X; otherwise return Y.

Result type:	The common arithmetic type of X and Y.

Examples:	MIN(234,64) returns 64
	MIN(3.77e5,9.856e3) returns 9.8560E+03

13-22
PL/I Reference Manual	13.7		List of Built-in Functions

MOD

Category:		Arithmetic
Format:	MOD(X,Y)

Parameters:		X and Y are arithmetic expressions.

Result:	Returns the value X modulo Y.
Algorithm:		If Y=O then return X, otherwise return X
	(Y)-FLOOR(X/(Y)).

Result type:		The result is a value having the common arithmetic
type of X and Y.

Examples:		MOD(7,3) returns 1
	MOD(-7,3) returns 2
	MOD(7,-3) returns -2
	MOD(-7,-3) returns -1

Note: unless Y=O, MOD(X,Y) always returns a value with the same
sign as Y, and less than ABS(Y) in magnitude.

NULL

Category: 		Miscellaneous

Format: 	NULL[()]

Result:	Returns the null pointer value that points to an
invalid storage location.

Result type: 		POINTER

13-23
PL/I Reference Manual	13.7	List of Built-in Functions

ONCODE

Category:	Condition
Format:	ONCODEO
Result:	Returns the value of the error subcode of the most
	recently signaled condition. The error conditions
	and their corresponding error numbers are listed in
	Section 9.4, Table 9-1.

Result type:	FIXED BINARY

ONFILE

Category:	Condition
Format:	ONFILEO
Result:	Returns the filename for which the most recent
	ENDFILE or ENDPAGE condition was signaled.

Result type: 	CHARACTER

13-24
PL/I Reference Manual	13.7		List of Built-in Functions

ONKEY

Category:		Condition
Format:	ONKEYO
Result:	Returns the character string value of the key for the
	record that signaled an input/output or conversion
	condition.

Result Type: 		CHARACTER

PAGENO

Category:		Miscellaneous
Format:	PAGENO(F)
Parameter:		F is a file value.
Result:	Returns the page number of the file specified by F.
	The file must have the PRINT attribute.

Result type:		FIXED BINARY

13-25
PL/I Reference Manual	13.7	List of Built-in Functions

RANK

Category:	Conversion
Format:	RANK(C)
Parameter:	C is a character value of length one.
Result:	Returns the integer representation of the ASCII
	character C (see Appendix F).

Result type:	FIXED BINARY

Algorithm:	RANK(C) equals INDEX(COLLATEO,C) -1
Examples:	RANK('Y') returns 89
	RANK('51) returns 53
		REVERSE
Category:	String
Format:	REVERSE(S)

Parameters:	S is a character string expression

Result:	Returns a string the same length as S, with the
	characters in reverse order.

Result Type: 	CHARACTER

Examples:	REVERSE('ABCI) returns 'CBA'

13-26
PL/I Reference Manual	13.7		List of Built-in Functions

ROUND

Category:		Arithmetic
Format:	ROUND(X,K)

Parameters:		X is an arithmetic expression.
K is a signed integer constant.

Result:	Returns X rounded to K digits to the right of the
	decimal point if K >= 0. Returns X rounded to -K
	digits to the left of the decimal point if K < 0.
Algorithm:		Return SIGN(X)*FLOOR(ABS(X)*B**N)+0.5)/B**N
	where		B=2 if X is BINARY
		B=10 if X is DECIMAL
	and		N=K if X is FIXED
	else		N=K-E if X is FLOAT and E is the exponent of
		X.

Result type:		Same as X

Examples:		ROUND(12345.24689,3) returns 12345.24700
	ROUND(34567.12345,-3) returns 35000.00000

SEARCH

Category:		String
Format:	SEARCH(S,C)

Parameters:		S is a character string expression.
C is a character string expression.

Result:	Returns an integer value indicating the position of
	the first character in S that matches a character in
	C. Returns a 0 if no characters in S occur in C.

Result Type:		FIXED BINARY

Examples:		SEARCH('$***12.951,101234567891) returns 5

13-27
PL/I Reference Manual	13.7	List of Built-in Functions

SIGN

Category:	Arithmetic
Format:	SIGN(X)
Parameter:	X is any arithmetic expression.
Result:	Returns -1, 0, or 1 to indicate the sign of X.
Algorithm:	If X < 0 then return -1
	If X = 0 then return 0
	If X > 0 then return +1

Result type:	FIXED BINARY

Examples:	SIGN(-76.45e4) returns -1
	SIGN(199.98) returns 1

SIN

Category: 	Mathematical

Format: 	SIN(X)

Parameter:	X is an arithmetic expression.

Result:	Returns the sine of X in radians.

Result type:	FLOAT BINARY

Algorithm:	Chebyshev polynomial approximation

Examples:	SIN(3.1415/6.0) returns 4.999866265466036E-001

13-28
PL/I Reference Manual	13.7		List of Built-in Functions

SIND

Category:- 		Mathematical

Format: 	SIND(X)

Parameter:		X is an arithmetic exr)ression.

Result:	Returns the sine of X in degrees.

Result type:		FLOAT BINARY

Algorithm:		SIND(X) equals SIN(X*PI/180)

Examples:-		SIND(O.50) returns 8.7265340E-03
	SIND(O.50000) returns 8.726534433662890E-03

SINH

Category:- 		Mathematical

Format: 	SINH(X)

Parameter:		X is an arithmetic expression.

Result:	Returns the hyperbolic sine of X.

Result type:		FLOAT BINARY

Algorithm:		SINH(X) equals (EXP(X)-EXP(-X))/2

Examples:		SINH(2-75) returns 7.7893520E+00
	SINH(2.75000) returns 7.789351940155029E+000

I----

13-29
PL/I Reference Manual	13.7		List of Built-in Functions

SQRT

Category:	Mathematical
Format:	SQRT(X)
Parameter:	X is an arithmetic expression, X >= 0.
Result:	Returns the square root of X.
Result type:	FLOAT BINARY
Algorithm:	Newton's method
Error
E-o-ndition:	If X < 0, the run-time system signals the ERROR(3)
	condition.
Examples:	SQRT(2) returns 1.4142135E+00
	SQRT(2.0000000) returns 1.414213562373094E+000
		SURSTR

Category:	String
Format:	SUBSTR(X,I[,J])
Parameters:	X is a string, either bit or character.
	I is a FIXED BINARY value.
	J is a FIXED BINARY value.
Result:	Returns a string that is a copy of the string X
	beginning at the Ith element and for a length J. If
	J is not given, it defaults to the length of the
	remainder of the string, equal to LENGTH(X)-I+l.
Result type:	Same as X

Error
Condition:	None.	If the arguments are out of range,
	unpredictable results can occur.
Examples:	If word = 'Digital Research'
	s = '01110101'b
	then
	SUBSTR(word,ll) returns search
	SUBSTR(S,4,2) returns 10
		13-30
PL/I Reference Manual	13.7		List of Built-in Functions

TAN

Category: 		Mathematical

Format: 	TAN(X)

Parameter:		X is an arithmetic expression.

Result:	Returns the tangent of X in radians.

Result type:		FLOAT BINARY

Algorithm:		TAN(X) equals SIN(X)/COS(X)
Error
Condition:		If COS (X) equals 0, then the run-time system signals
	the ERROR(3) condition.
Examples:		TAN(3.1415/4-0) returns 9.999536742781560E-001

TAND

Category: 		Mathematical

Format: 	TAND(X)

Parameter:		X is an arithmetic expression.

Result:	Returns the tangent of X in degrees.

Result type:		FLOAT BINARY

Algorithm:		TAND(X) equals TAN(X*PI/180)
Error
Condition:		If COS(X*PI/180) equals 0, the run-time system
	signals the ERROR(3) condition.
Examples:		TAND(O.50000) returns 8.72686747144603E-003

13-31
PL/I Reference Manual	13.7	List of Built-in Functions

TANH

Category: 	Mathematical

Format: 	TANH(X)

Parameter:	X is an arithmetic expression.

Result:	Returns the hyperbolic tangent of X.

Result type:	FLOAT BINARY

Algorithm:	TANH(X) = (EXP(X)-EXP(-X))/(EXP(X)+EXP(-X))

Examples:	TANH(2.75) returns 9.9185970E-01
	TANH(2.75000) returns 9.9185973405838OOE-001

TIME

Category:	Miscellaneous
Format:	TIMEO

Parameters: 	None

Result:	Returns a character string representing the current
	time in the form, HHMMSStttttt where
	HH is the current hour (00-23)
	MM is the minutes (00-59)
	SS is the seconds (00-59)
	tttttt is the microseconds

Result Type: 	CHARACTER(12)

Examples:	TIMEO returns '133427000000'
Remarks:	Only available if supported by operating system.
	tttttt is only as accurate as the system clock, and
	in most cases will be much less precise than one
	microsecond. If not supported, TIME returns blanks.

13-32
PL/I Reference Manual	13.7		List of Built-in Functions

TRANSLATE

Category:		String
Format:	TRANSLATE(XIYIIZI)

Parameters:		X is a character expression.
Y is a character expression.
Z is a character expression.

Result:	If Z does not occur, it is assumed to be COLLATEO.
	If Y is shorter than Z, it is padded to the right
	with blanks until its length equals the length of Z.
	Any occurrence of a character in Z in the string X
	is then replaced by the character in Y corresponding
	to that character in Z.

Result type:		Same as X

Examples:		TRANSLATE('BDA',1l231,'ABC1) returns 12Dl'

TRIM

Category:		String
Format:	TRIM (S [, L,T]

Parameters:		S, L, and T are character string expressions.

Result:	TRIM(S) returns a character string with the leading
	and trailing blanks removed. TRIM(S,L,T) returns a
	character string with all leading characters of S
	that appear in L removed, and all trailing
	characters of S that appear in T removed.

Result Type: 		CHARACTER

Examples:		TRIM(' ABCDE	) returns	IABCDE'
	TRIM('$***1.23			l) returns 11.231

13-33
PL/I Reference Manual	13.7	List of Built-in Functions

TRUNC

Category:	Arithmetic
Format:	TRUNC(X)
Parameter:	X is any arithmetic expression.
Result:	Returns the integer portion of X.
Algorithm:	If X < 0 then return (CEIL(X))
	If X >= 0 then return (FLOOR(X))

Result type:	A signed integer value of the same type as X.

Examples:	TRUNC(52.146) returns 52
	TRUNC(-52.146) returns -52
		UNLOCK
Category:	Miscellaneous
Format:	UNLOCK(F,I)
Parameter:	F is a file constant or variable that must be opened
	in Shared mode. I is a FIXED BINARY(15) integer that
	gives the record number relative to the record size
	specified in the ENVIRONMENT option.
Result:	Returns a one-bit if the operation is successful or a
	zero-bit if unsuccessful. Unlocks the record
	specified by I so that other users can access it.
	The record remains unlocked until locked with the
	LOCK function, or the program terminates.

Result Type: 	BIT(l)

Remark:	Only available if supported by operating system.

13-34
PL/I Reference Manual	13.7		List of Built-in Functions

UNSPEC

Category:		Miscellaneous
Format:	UNSPEC(X)
Parameter:		X is a reference to a data item whose internal
	representation in memory is 16 bits or less.
Result:	Returns the contents of the storage location occupied
	by X.
Result type:		A bit string whose length equals the length of the
	internal representation of the data item associated
	with X.
Examples:		If num = 25000	(FIXED BINARY) then
	UNSPEC(num) returns 0110000110101000
		VERIFY

Category:		String
Format:	VERIFY(S,C)
Parameters:		S is a character expression.
	C is a character expression.
Result:	Returns integer value 0 if each of the characters in
	S occurs in C. Otherwise, returns an integer that
	indicates the position of the leftmost character of
	S that does not occur in C.
Result type:		FIXED BINARY

Examples:
	VERIFY('ABCDE','ABDE') returns 3
VERIFY('ABC1231,'lA2B3C4D') returns 0
VERIFY('','A') returns 0
VERIFY('A','') returns 1
	End of Section 13
		13-35
Section 14
PL/1 Statements

This section lists the PL/I statement formats in alphabetical order.

14.1 The ALLOCATE Statement
ALLOCATE based-variable SET(pointer-variable);

Examples:

declare
	A character(16) based(P),
	P pointer;
	allocate A set(P);

14.2				The ASSIGNMENT Statement
	variable 		expression;

Examples:

B = C*D;
unspec (E)		F (I);

14.3 The BEGIN Statement
BEGIN;

14.4 The CALL Statement
CALL proc-name [(sub-l,...,sub-n)1 [(argument-list)];

Examples:

call Pl;
call P2(A,B,C);

14.5 The CLOSE Statement
CLOSE FILE(file-id);

Examples:

close file(INP);
close file(B:PAYFINES.DAT);

14-1
PL/I Reference Manual	14.6	The DECLARE Statement

14.6	The DECLARE Statement (for scalar variables)

DECLARE name [attribute-list];

Examples:

declare index - count fixed binary(15);
declare pi float binary(53);
declare overtime_pay fixed decimal(6,2);

14.7	The DECLARE Statement (for array variables)

DECLARE name(bound-pair .... ) [attribute-list];

Examples:

declare B(-2:5,-5:5,5:10);
declare class_grades(30:100) character(25) varying;

14.8 The DECLARE Statement (for structure variables)
DECLAREJDCL (level] name [attribute-list] ...
[,[level] name [attribute-list]];

Examples:

declare A fixed;
declare 1 B,
2 C NAME character(20),
2 D ADDRESS,
3 STREET character(20),
3 CITYST character(20),
3 ZIP character(5);
declare ZZ(10) fixed;
declare A fixed external;

14.9	The DECLARE Statement (for ENTRY data)

DECLARE proc-name	[(bound-pair-1. ... bound-pair-n)]
[ENTRY(parameter-list)]
(EXTERNAL] [VARIABLE]
(RETURNS(return-att)];

Examples:

declare x entry;
declare p(0:10) entry(fixed,float) variable;
declare r returns(character(10));

14-2
PL/I Reference Manual	14.10		The DECLARE Statement

14.10		The DECLARE Statement (for FILE data)

DECLARE file-id FILE (VARIABLE);

Examples:

declare f5 file;
declare f(5) file variable;

14.11		The DO Statement

DO (control-variable] do-specification;

where do-specification can be one of the following:

start-exp [TO end-exp] [BY incr-exp] [WHILE(condition))
start-exp [BY incr-exp] [TO end-exp] [WHILE(condition)]
start-exp [REPEAT repeat-exp] [WHILE(condition)]

Examples:

do J=O;
do while(A<B);
do J = 1 TO 10;
do K = 10 TO 0 BY -2 while(A<B);
do P=START repeat P->NEXT while(P^=NULL);

14.12		The END Statement

END [label];

Examples:

end;
end Pl;

14.13		The FORMAT Statement

label: FORKAT(format-list);

Examples:

Ll: format(A(5));
L2: format(10 B4(2));

14-3
PL/I Reference Manual	14.14	The FREE Statement

14.14 The FREE Statement
FREE [pointer-variable->] based-variable;

Examples:

free A;
free P->A;

14.15 The GET EDIT Statement

GET [FILE(file id)] [SKIP[(nl)]]
EDIT(input-list) (format-list);

Examples:

get edit(A,B,C)((3)f(5,2));
get file(INP) edit((Z(I) do I = 1 to 3))(A);

14.16 The GET LIST Statement
GET [FILE(file-id)] [SKIP[(nl)]] LIST(input-list);

Examples:
get list(X,Y,Z);

14.17 The GOTO Statement
GOTOIGO TO label-constantliabel-variable;

Examples:

go to the_end;
goto lab(K);

14.18 The IF Statement

IF condition THEN action-1 [ELSE [action-2]]

Examples:

if A=2 then B=A**2;
else;

if J>K then I = I+l;
else I = 1+3;

14-4
PL/I Reference manual	14.19		The %INCLUDE Statement

14.19		The %INCLUDE Statement

%INCLUDE Ifilespec';

Examples:

%include 'mathlib.pli';
%include 'constnts.dcl';

14.20		The NULL Statement

Examples:

else

14.21		The ON Statement

ON condition-name ON-unit,

Examples:

on endfile(INP)
begin;
put list('END OF INPUT');
stop;
end;

on error put list(oncodeo);

14.22		The OPEN Statement

OPEN FILE(file-id) [file-attributes];

Examples:

open file(INP) input;
open file(SYSPRINT) output;

14-5
PL/I Reference Manual	14.23	The PROCEDURE Statement

14.23	The PROCEDURE Statement

proc-name:	PROCEDUREIPROC [(parameter-list)]
	[OPTIONS(option.... )) [RETURNS(attribute-list)]
	(RECURSIVE]

Examples:

Pl:	proc(A,B,C);
P2:	procedure (ZZ) returns(float);
P3:	proc(N) returns(fixed bin) recursive;
P4:	procedure options(main);

14.24	The PUT EDIT Statement

PUT	[FILE(file id)] [SKIP[nl]] [PAGE]
EDIT(outpu~-list)(format-list);

Examples:

put edit(A,B,C) (F(5,2),X(3),2E(l0,2));
put edit((Z(I) do I = 1 to 10))(A);

14.25	The PUT LIST Statement

PUT [FILE(file-id)] [SKIP[(nl)]] [PAGE] LIST (output-list);

Examples:

put list(A,B,C);
put file(F) list((Z(I) do I = 1 to 10));

14.26	The READ Varying Statement

READ (FILE(file-id)] INTO(v);

Examples:
read file(F) into(buffer);

14.27	The READ Statement (for SEQUENTIAL RECORD files)

READ FILE(file-id) INTO(x);

Examples:
read file(INP) into(XX);

14-6
PL/I Reference Manual	14.28		The READ with KEY Statement

14.28		The READ with KEY Statement

READ FILE(file-id) INTO(X) KEY(k);

Examples:

read file(INP) into(STRUC) key(IKEY);

14.29		The READ with KEYTO Statement

READ FILE(file-id) INTO(x) KEYTO(k);

Examples:

read file(INP) into(z) keyto(IKEY);

14.30		The %REPLACE Statement

%REPLACE identifier BY constant;

Examples:

%replace true by 111b;
%replace		rows	by 10,
	columns		by 6;

14.31		The RETURN Statement

RETURN Hreturn-exp)];

Examples:

return;
return(X);
return(A**2);

14.32		The REVERT Statement

REVERT condition-name;

Examples:

revert error;
revert endfile;

14-7
PL/I Reference Manual	14.33	The SIGNAL Statement

14.33 The SIGNAL Statement
SIGNAL condition-name;

Examples:

signal error;
signal endfile(sysin);

14.34 The STOP Statement
STOP;

14.35 The WRITE Varying Statement (for STREAM files)
WRITE [FILE(file-id)] FROM(v);

Examples:

declare (XX,YY) character(200) varying;
write file(OUTPUT) from(XX);
write from(YY);

14.36 The WRITE Statement (for SEQUENTIAL RECORD files)
WRITE FILE(file-id) FROM(x);

Examples:

write file(OUTP) from (XX);
write file(F) from(STRUC);

14.37 The WRITE with KEYFROM Statement
WRITE FILE(file-id) FROM(x) KEYFROM(k);

Examples:
write file(KP) from(REC) keyfrom(IKEY);

End of Section 14

14-8
Section 15
Data Attributes

This section summarizes all the PL/I data attributes and storage
classes. Abbreviations of attributes are included. Refer to the
relevant sections for full details of the attributes.

15.1		ALIGNED

ALIGNED is a the attribute that usually forces storage boundary
alignment of a variable. It has no effect in PL/I but is included
for compatibility with other implementations. For example,

declare A(0:3) bit(4) aligned;

15.2		AUTOMATIC I AUTO

AUTOMATIC is the storage class that specifies that storage is
allocated to the variable upon activation of the block containing
the declaration. In PL/I, automatic storage is statically
allocated, except for recursive procedures. For example,

declare A fixed binary; /* is equivalent to
declare A fixed binary auto;

15.3		BASED or BASED(p) or BASED(q0)

BASED is the storage class that specifies user-controlled allocation
for a variable. In this case, p is a pointer variable, and q is a
pointer-valued function. For example,

declare A fixed binary based,
B(5) character(10) based(p),
C fixed binary based(fo);

15.4		BINARY I BIN or BINARY(p) I BIN(p)
BINARY defines a BINARY variable with precision p.

	for FIXED variables		p <= 15
	for FLOAT variables		p <= 53
For example,

declare I fixed binary(7),
F float binary(40);

15-1
PL/I Reference Manual	15.5 	BIT

15.5	BIT(n)

BIT (n) defines a bit string of length n, where n <= 16. For
example,

declare A bit(3);

15.6	BUILTIN

BUILTIN specifies that the declared name is one of the PL/I built-in
functions (BIFs). If you declare a BIF name in any block as a
variable, then you must redeclare it with the BUILTIN attribute if
you want to reference it as the BIF in any contained block. For
example,

declare sqrt builtin;

15.7	CHARACTER(n) I CHAR(n)

CHARACTER (n) defines a character string of length n, where n <=254.
For example,

declare A character(10),
B(5) character(4);

15.8	DECIMAL[(p[,q1)1 I DEC[(p[,q])]

DECIMAL defines a decimal number with precision and scale (p,q),
where p <= 15 and q <= p. If you do not specify q, the default is q
= 0. If you do not specify either p or q, PL/I defaults to (7,0)
For example,
	declare A fixed decimal(6,2);

15.9	ENTRY[(parameter-list)]

ENTRY defines entry values, where parameter-list is the list of the
parameters as given in the PROCEDURE definitions of the entry
values. For exampler

declare		H entry,
	Z entry(10) (fixed),
	Y entry(float) returns(float),
X entry variable;

15-2
PL/I Reference Manual	15.10 		ENVIRONMENT(options)

15.10 ENVIRONMENT(options) I ENV(options)

ENVIRONMENT defines fixed- and variable-length record sizes for
RECORD files, internal buffer sizes, the file open mode, and the
password protection level. Options is one or more of the following:

Locked I L
ReadonlT I R
Shared				S
Passwordf(level)] I P[(level)]
Fixed(i)				F(i)
Buff(b) 				B(b)

where i is the fixed-record length, and b is the internal buffer
size. Both are expressed as integer constants For example,

open file keyed env(f(100),b(4000));
open file(f6)		input direct title('d:accounts.new;topazl)
	env(shared,password(d),f(100),b(2000));

15.11 EXTERNAL I EXT

EXTERNAL defines the scope of the declared item to be EXTERNAL.
That is, the item is known in all blocks where it is declared as
EXTERNAL. For example,

declare A character(8) external;

15.12 FILE
FILE defines file data. For example,

declare F file,
FV file variable;

15.13 FIXED[(p[,ql)l

FIXED defines fixed-point arithmetic data of precision and scale
factor (p,q). If specified for BINARY data, q must be 0. For
example,

declare A fixed binary,
B fixed decimal(5,2);

15-3
PL/I Reference Manual	15.14 	FLOAT

15.14	FLOAT[(p)]

FLOAT defines floating-point arithmetic data of precision p, where p
<= 53. For example,

declare A float binary;

15.15	INITIAL(value-list) I INIT(value-list)

INITIAL causes the compiler to assign initial values to a STATIC
variable before program execution. The value-list is a list of
constants, separated by commas, that can be converted to the
variable type being initialized. Any constant in the list can be
preceded by a repetition factor in parentheses. For example,

declare A character(3) static initial('ABC'),
B(2) fixed binary static initial((2)5);

15.16	LABEL

LABEL defines a LABEL variable. For example,
declare somewhere label;

15.17	PARAMETER

PARAMETER is the storage class the compiler assigns to data items
that appear in a parameter-list. Storage for the parameters is
allocated when the calling procedure passes the parameters to a
called procedure. In the example below, the compiler assigns x the
storage class PARAMETER.

Example:
	declare A entry(x float) external returns(float);

15.18 POINTER I PTR
POINTER defines a POINTER variable. For example,
declare (p,q) pointer;

15.19	RETURNS(attribute-list)

RETURNS (when used with the ENTRY attribute) describes the attribute
list	of the value returned by a function. For example,
	declare A entry(float) returns(fixed);

15-4
PL/I Reference Manual	15.20 		STATIC

15.20		STATIC

STATIC is the storage class that causes the compiler to allocate
storage before program execution. For example,

declare A character(10) static,
B fixed binary static initial(O);

15.21		VARIABLE

VARIABLE (when used with the FILE or ENTRY attributes) defines the
item as a variable instead of a constant. For example,

declare F file variable,
P entry variable;

15.22 VARYING I VAR
VARYING defines a varying length character string. For example,
declare A character(100) varying;

End of Section 15

15-5
Appendix A
Implementation Notes

Digital Research PL/I is based on American National Standard X3.74,
PL/I General Purpose Subset (Subset G) . Digital Research has
implemented PL/I on a variety of microcomputer architectures and
operating system environments.

This appendix describes the differences between the various
implementations, and the differences between these implementations
and the Subset G standard.

The following nomenclature is used in this appendix:

		DRI PL/I refers to all Digital Research implementations of
PL/I.

		PL/I-80" refers to any version of the 8-bit implementations of
PL/I for 8080-compatible microprocessors such as the 8080,
8085, and Z808 Features specific to a particular version are
designated with release numbers; that is, PL/I-80 R1.4.

		PL/I-86" refers to any version of the 16-bit implementations
of PL/I for 8086-compatible microprocessors such as the 8086
and 8088. Features specific to a particular version are
designated with release numbers; that is, PL/I-86 R1.0.

		DOS refers to the IBM Personal Computer Disk Operating System
Version 1.1.

A.1 DRI PL/I vs. PL/1 Subset G

DRI PL/I conforms to the Subset G standard with the following
exceptions:

DRI PL/I does not implement the attributes:

		DEFINED
		FLOAT DECIMAL
		PICTURE (it is implemented as an edit format item on output)

DRI PL/I does not implement *-extents in arrays or strings. DRI
PL/I does not implement expression extents in arrays or strings.
All extents must be constants.

DRI PL/I does not implement

A = scalar;

where A is an array variable.

A-1
PL/I Reference Manual	A.1	DRI PL/I vs. PL/I Subset G

DRI PL/I does not currently implement the keyword PARAMETER. Future
versions of PL/I-86 will implement this keyword.

DRI PL/I requires the third argument of SUBSTR of a bit-string be a
constant.

DRI PL/I does not implement some built-in functions. Table A-1
shows which built-in functions are not available in the respective
implementations.

Table A-1. Built-in Functions Not Implemented

PL/I-80	PL/1-86 R1.0,	PL/I-86 Rl.O(DOS)	PL/I-86 R1.2
I R1.1, and I	I
ATANH	ATANH	ATANH	ATANH
COPY	COPY	COPY	STRING
DATE	REVERSE	REVERSE	VALID
REVERSE	SEARCH	SEARCH
SEARCH	STRING	STRING
STRING	TRIM	TRIM
TIME	VALID	VALID
TRIM
VALID

DRI PL/I implements the following built-in functions as extensions
to the Subset G standard:

		ASCII
	RANK

In DRI PL/I, the %REPLACE statement is extended to allow multiple
replaces in a single statement.

DRI PL/I adds the following 1/0 facilities for ASCII file
processing:

	READ Varying and WRITE Varying statement forms for processing
variable-length ASCII records

	The GET EDIT statement is extended to full record input in A
format

DRI PL/I allows control characters in string constants. This
feature is incompatible with the ANSI standard and will be changed
in future releases of PL/I-86.

A-2
PL/I Reference Manual	A.1		DRI PL/I vs. PL/I Subset G

DRI PL/I allows statements such as

declare		numbers(10) character(10)
	static initial((10)10123456789');

In Subset G, you must use a (1) string replication factor of the
form

declare		numbers(10) character(10)
	static initial((10)(1)101234567891);

In DRI PL/I, an ON-unit cannot free storage for a variable that is
being used when the condition is signaled, or close the file for
which an 1/0 condition is signaled. The ON-unit must branch to a
non-local label.

DRI PL/I does not support par tially-subscr ipted, and/or partially
qualified mixed aggregate references that specify unconnected
storage.

DRI PL/I has a non-standard implementaion of RECURSIVE procedures
On entry, they copy onto the stack the static frame containing their
AUTOMATIC storage. On exit, such procedures copy the values present
on entry from the stack back to the static frame. If a RECURSIVE
procedure calls a subroutine and passes an AUTOMATIC variable by
reference, it passes the address of the variable in the static
frame. If the subroutine then calls the original RECURSIVE
procedure, nonstandard results can occur.

You can avoid non-standard results if you always force the compiler
to pass an argument by value when making a call inside a RECURSIVE
procedure. To pass an argument by value, enclose the argument in
parentheses.

A.2 Differences between PL/I-80 and PL/1-86

PL/I-80 and PL/I-86 R1.0 do not check bounds for the precision given
in a DECLARE statement. For example, given the declaration

declare		x fixed binary(35);

the compiler supplies the maximum precision (15) without issuing a
warning message.

PL/I-80 and PL/I-86 R1.0 do not verify that a function procedure
contains a RETURN statement.

PL/I-80 and PL/I-86 R1.0 do not revert ON-units when exiting a BEGIN
block.

A-3
PL/I Reference Manual	A.2 PL/I-80 vs. PL/I-86

PL/I-80 and PL/I-86 R1.0 do not create a dummy variable for a
constant argument. You can force the compiler to create a dummy
argument by enclosing the constant in parentheses.

PL/I-80 does not support comparison operations for FIXED BINARY
values whose sum or difference is greater than 32767 in absolute
value.

PL/I-80 and PL/I-86 R1.0 implement a condition stack which has 16
levels. In any given block, PL/I-80 and PL/I-86 R1.0 stack ON-units
for the same condition. Also, the same ON-unit established in an
embedded block is pushed onto the condition stack.

PL/I-86 Rl.l implements ON conditions correctly without
restrictions.

Note: PL/I-80 and PL/I-86 R1.0 allow a maximum of 16 ON-units to
be enabled at any given point in a program. Enabling more than 16
ON-units is a nonrecoverable error. The run-time system stops
processing and outputs the following message:

Condition Stack Overflow

In PL/I-80 and PL/I-86 R1.0, you cannot declare a variable based on
a pointer that is a member of a structure. For example, the
following		declaration is invalid:
	declare
		1	my-structure,
			2 some-data fixed binary(7),
			2 p pointer,
		x	float binary based(p);

PL/I-80 produces relocatable object code in the Microsofte format.
This format restricts the length of external names to 6 characters.

PL/I-86 produces relocatable object code in the Intel(D format.
There are no restrictions on the length of external names with this
format.

PL/I-80 R1.4 and PL/1-86 Rl.l implement password protection for
files in the ENVIRONMENT attribute, and implement the LOCK and
UNLOCK built-in functions for locking and unlocking individual
records in a file. PL/I-86 R1.0 does not implement these features.

PL/I-80 R1.4 and PL/I-86 Rl.l implement double-precision FLOAT
BINARY data; PL/I-86 R1.0 does not.

A-4
PL/I Reference manual	A.2 PL/I-80 vs. PL/I-86

PL/I-86 uses the IEEE format for representing single-precision,
floating-point data; PL/I-80 does not. Thus, there is a fundamental
data format incompatibility between PL/I-80 and PL/I-86. A PL/I-86
program cannot read floating-point data written to disk files with
PL/I-80. Appendix B contains descriptions of each format, and a
procedure for converting from PL/I-80 format to PL/I-86 format.

PL/I-86 Rl.l permits the characters @ (at sign) , and # (number sign)
to appear in identifiers.

In PL/I-86 R1.2, the COLLATE built-in function returns a character
string of length 256 instead of 128.

A.3 PL/I-86 Running Under DOS

The DOS operating system does not support password protection for
files, or record locking and unlocking for individual records. See
Section 10.1 or the Programmer's Guide for more information.

Under DOS, physical device names end with a colon. For example, the
system console is CON: and the system list device is LPT1: or PRN:.
Under CP/M, the coresponding names are $CON and $LST. See Section
10.1 or the Programmer's Guide for more information.

A.4 Summary of Differences

Table A-2 summarizes the differences among the various
implementations.

A-5
PL/I Reference manual	A.4	Summary of Differences

Table A-2. Summary of Implemetation Differences

Feature		PL/1-80	PL/I-80	PL/1-86	PL/I-86	PL/1-86	PL/I-86
	I		R1.3		R1.4		RI.0	R1.0 D		Rl.l		R1.2
Object Code
format	Microsoft	Microsoft	Intel	Intel	Intel	Intel

S.P. Floating
point format	non-IEEE	non-IEEE	IEEE	IEEE	IEEE	IEEE

D.P. Float
Binary data		No	Yes		No		No	Yes	Yes
Password
Protection		No	Yes		No		No	Yes	Yes
Record Locking/
Unlocking		No	Yes		No		No	Yes	Yes
Condition
Stack Depth	16 levels	16 levels	16 levels	16 levels	unlimited	unlimited

Device Names	$CON,$LST	$CON,$LST	$CON,$LST	CON:,LPTI:	$CON,$LST 	$CON,$LST

@, # valid in
identifiers	No	No	No	No	Yes	Yes
Length of string
returned by
COLLATEO	128	128	128	128	128	256
Variables based
on pointer in a
structure	No	No	No	No	Yes	Yes
Create dummy
variables for
constant
argument	No	No	No	No	Yes	Yes
Revert ON-units
when exiting
BEGIN block	No	No	No	No	Yes	Yes
FIXED BINARY
comparisons
>1327671	No	No	Yes	Yes	Yes	Yes

BIFS not
supported	ATANH,COPY	ATANH,COPY	ATANH,COPY	ATANH,COPY	ATANH,COPY	ATANH
	DATE,REVERSE	DATE,REVERSE	REVERSE	REVERSE	REVERSE	STRING
	SEARCH,STRING	SEARCH,STRING	SEARCH,TRIM	SEARCH,TRIM	SEARCH,TRIM	VALID
	TIME,TRIM	TIME,TRIM	STRING,VALID	STRING,VALID	STRING,VALID
	VALID	VALID
			End of Appendix A
Appendix B
Internal Data Representation

This appendix describes PL/I internal data formats. This knowledge
is vital when using based variables to overlay storage so you do not
destroy adjacent storage locations. Knowledge of the internal data
representation is also useful when you want to interface assembly
language routines with high-level language programs and the PL/I
Run-time Subroutine Library.

Note: in this section PL/I applies to both PL/I-80 and PL/I-86
unless otherwise indicated.

B.1		FIXED BINARY Representation

PL/I stores FIXED BINARY data in one of two forms, depending upon
the declared precision. It stores FIXED BINARY values with
precision 1-7 in single-byte locations, and values with precision 8
15 in word (double-byte) locations. With multibyte storage, PL/I
stores the least significant byte at the lowest memory address.

PL/I represents all FIXED BINARY data in two's complement form,
allowing single-byte values in the range -128 to +127, and double
byte values in the range -32768 to +32767.

Figure B-1 shows the representation of storage in both single-byte
and double-byte locations for the values 0, 1, and -2. Each boxed
value represents a byte of memory, and is shown in both binary and
hexadecimal values.

B-1
PL/I Reference Manual	B.1 FIXED BINARY Representation

0000 0000 0000 0000j

00 0

FIXED BINARY(7)	FIXED BINARY(15)

0000 0001 0000 00001

01 0

FIXED BINARY(7)	FIXED BINARY(15)

lill 1110 1111 lill

FE F

Figure B-1. FIXED BINARY Representation

B.2 FLOAT BINARY Representation

B.2.1 Single-precision

PL/I-80

PL/I-80 stores single-precision floating-point binary data in the
Microsoft format. This format uses four consecutive byteSr with the
32 bits containing the following fields: a 23-bit mantissa, a sign
bitr and an 8-bit exponent. The least significant byte of the
mantissa is in the lowest memory address.

I	exponent I s I 	mantissa

31	23 22	0

Figure B-2. PL/I-80 Single-precision Floating-point Format

The Microsoft format normalizes floating-point numbers so the most
significant bit of the mantissa is always 1 for nonzero numbers.
Because the most significant bit of the mantissa must be 1 for
nonzero numbers, this bit position is used for the sign. This is
called using an implicit, normalized bit, and the binary point is
considered to be immediately to the left of the normalized bit.

B-2
PL/I Reference Manual	B.2		FLOAT BINARY Representation

To make certain kinds of comparisons easier, the binary exponent
byte has a bias of 128 (decimal) or 80 (hexadecimal), so that 81
represents an exponent of 1 while 7F represents an exponent of -1.
A zero mantissa has an exponent byte of 00.

Suppose a floating-point binary value appears in memory as
00 1 00 1 40T-811

3			2	1 	0

The bit-stream representation has the following form:

8		1	4	0	0	0	0 	0

1000 0001 0100 0000 0000 0000 0000 0000

When the bias is subtracted from the exponent, the true binary
exponent is 1.

	1000 0001
-1000 0000

0000 0001

The mantissa appears as

1 01100 0000 0000 0000 0000 0000
I si
The high-order bit equal to zero indicates that the sign is
positive. Restoring the implicit, normalized bit produces the bit
stream

1100 0000 0000 0000 0000 0000

Because the binary point is one position to the left of the implicit
normalized bit, the value of the mantissa is

1100 0000 0000 0000 0000 0000

1100 ... represents 2-1 + 2-2 . multiplying by the true exponent 21
we get

21 (2-		+ 2-2	2(1/2 + 1/4) = 1 + 1/2 = 1.5

Thus, the four-byte value:
1 00 1 00 1 40 18q

is the floating-point binary representation of the decimal number
1.5.

B-3
PL/I Reference manual	B.2	FLOAT BINARY Representation

PL/I-86

PL/I-86 stores single-precision, floating-point binary numbers using
the IEEE format. This format uses four consecutive bytes, with the
32 bits containing the following fields: a 23-bit mantissa, an 8-bit
exponent, a sign bit. The least significant byte of the mantissa is
in the lowest memory address.

Isl exponent I mantissa 1
31 30	23 22 	0

Figure B-3. IEEE Single-precision Floating-point Format

The IEEE format normalizes floating-point numbers so the most
significant bit of the mantissa is always 1 for nonzero numbers.
Because the most significant bit of the mantissa must be 1 for
nonzero numbers, this bit is not stored. This is called using an
implicit, normalized bit, and the binary point is considered to be
immediately to the right of the normalized bit.

In IEEE format (single-precision) , the binary exponent has a bias of
127 (decimal) or 7F (hexadecimal) so 80 represents an exponent of +1
while 7E represents an exponent of -1.

Suppose a floating-point binary value appears in memory as
_F7
1 00 100 jC0 3F

3	2	1 	0

The bit-stream representation has the form:

3	F	C	0	0	0	0 	0

0011 1111 1100 0000 0000 0000 0000 0000

The high-order bit equal to zero indicates the sign is positive, and
the exponent has a bias of 7F, so the true binary exponent is 0.

0	0111111111 1000 0000 0000 0000 0000 000

s

Restoring the implicit, normalized bit, produces the bit stream:

1100 0000 0000 0000 0000 0000

B-4
PL/I Reference Manual	B.2		FLOAT BINARY Representation

Because the binary point is one position to the right of the
implicit, normalized bit, the value of the mantissa is

1 100 0000 0000 0000 0000 0000

1 1 in binary represents 20+2-1. Multiplying by the true exponent
20, we get

20 (20 + 2-1		1 (1 + 1/2) = 1 + 1/2 = 1. 5

Thus, the four-byte value:

Fj

is the floating-point binary representation of the decimal number
1.5.

You can convert data written in the non-IEEE format to the IEEE
format by using the procedure in Listing B-1.

B-5
PL/I Reference Manual	B.2	FLOAT BINARY Representation

SPBOT086: procedure(f) returns(float binary(24));

declare
	(f,r) float binary(24),
	b fixed binary(7),
	(fp,rp) pointer;
	declare
1 f80 based (fp)
	2 (wordO,wordl) bit(16);
	declare
1 f86 based(rp),
	2 (wordO,wordl) bit(16);
	declare
1 f8Oover based(fp),
2 (byteO,bytel,byte2,byte3) fixed binary(7);

fp = addr(f);
rp = addr(r);
r = f; /* copy the whole source to target

/* copy exponent and adjust bias by 2:
1 for 127 vs 128, 1 for 1. not .1

b = byte3 - 2;
substr(rp->f86.wordl,2,8) = unspec(b);

/* copy sign bit */
substr(rp->f86.wordl,1,1) = substr(fp->f80.wordl,9,l);
return(r);
end SP80T086;

Listing B-1. Floating-point Format Conversion Procedure

B.2.2 Double-precision

PL/I-80 R1.4 and PL/I-86 R1.1 store double-precision, floating-point
binary data using the IEEE format. This format uses eight
consecutive bytes, with the 64 bits containing the following
fields: a 52-bit mantissa, an 11-bit exponent, and a sign-bit.

	s I expon(		mantissa	I
63 62	51 		0

Figure B-4. Double-precision Floating-Point Format
PL/I Reference Manual	B.2		FLOAT BINARY Representation

The IEEE format normalizes floating-point numbers so the most
significant bit of the mantissa is always 1 for nonzero numbers.
Because the most significant bit of the mantissa must be 1 for
nonzero numbers, this bit is not used for the sign. This is called
using an implicit normalized bit, and the binary point is considered
to be immediately to the right of the normalized bit.

In IEEE format (double-precision) , the exponent has a bias of 1023
(decimal) or 3FF (hexadecimal) so 400 represents an exponent of +1
while 3FE represents an exponent of -1.

For example, suppose that a floating-point binary value appears in
memory as shown in the following example:

)IOOIC01431COI

Low	High

In this case, the mantissa is a bit stream of the form,

3		C 	0

0011 1100 0000 . . .

Restoring the implicit, normalized bit produces

1001 1110 0000 . . .

The exponent evaluates as follows:

C		0 	4

1100 0000 0100

The high-order bit is 1 so the sign is negative. Ignoring the sign
bit yields an exponent of

4		0 	4
0100 0000 0100

which has a bias of 3FF, so the true binary exponent is

	404
-3FF

5

B-7
PL/I Reference Manual	B.2	FLOAT BINARY Representation

Therefore, the binary number is

1001 11 10 0000 . ..

which is 39.5 in decimal. Thus, the eight-byte value:
I 001001001001001CO1431CO

is the double-precision float-binary representation of the decimal
number -39.5.

B.3	FIXED DECIMAL Representation

PL/I stores FIXED DECIMAL data items in ten's complement packed BCD
(Binary Coded Decimal) form. Each BCD digit occupies a half-byte,
or nibble. PL/I stores the least significant BCD pair at the lowest
memory address, with one BCD digit position reserved for the sign.
Positive numbers have a 0 sign, while negative numbers have a 9 in
the high-order sign digit position.

The number of bytes occupied by a FIXED DECIMAL number depends upon
its declared precision. Given a decimal number with precision p,
PL/I reserves a number of bytes equal to

FLOOR((p + 2)/2)

where p varies between 1 and 15. This results in a minimum of 1
byte and a maximum of 8 bytes to hold a FIXED DECIMAL data item.

For example, if you declare the number 12345 with precision 5, then
PL/I reserves FLOOR((5 + 2)/2) = 3 bytes of storage and represents
the number as the following:

45	23	01

PL/I stores negative FIXED DECIMAL numbers in ten's complement form.
To derive the ten's complement of a number, first derive the nine's
complement and then add 1 to the result. For example, the number -2
expressed in ten's complement is

(9 - 2) + 1 = 8

Adding the sign digit gives

98

If you declare -2 with precision 5, then PL/I represents it as
98 1 99 1 9fl

B-8
PL/I Reference Manual	B.4		CHARACTER Representation

BA		CHARACTER Representation

PL/I stores character data in one of two forms, depending upon the
declaration. It stores fixed-length character strings, declared as
CHARACTER(n) in n contiguous bytes, with the first character in the
string stored lowest in memory.

PL/I reserves n+l bytes for variables declared as CHARACTER(n)
VARYING with the extra byte holding the length of the character
string. The length can range from 0 to 254. The maximum length of
either type of string is 254 characters.

As an example, suppose the variable A is declared as CHARACTER(20).
The assignment

A = 'Walla Walla Wash';

results in the following storage allocation:

1WIallIllalWlWlalllllalylWlalsihlVlglXlklI
where b represents a blank. If A is declared as CHARACTER(20)
VARYING data, PL/I stores the same string as
1 101 W jai 11 11 al O(JWJaJ 11 11 al I/JWJaJ sl h llel)61J~1)61
where 10 is the (hexadecimal) string length.

B.5		BIT Representation

PL/I represents bit-string data in two forms, depending upon the
declared precision. It stores bit strings of length 1-8 in a single
byte, and bit strings of length 9-16 in a word (double-byte) value.
PL/I stores the least significant byte of a word value at the lowest
memory address. Bit values are stored left-justified, and if the
precision is not exactly 8 or 16 bits, the bits to the right are
ignored.

Figure B-5 shows the storage for the bit-string constant values
111b, 'AO'b4, and '1234'b4 in both single- and double-byte
locations. Each boxed value represents a byte.

B-9
PL/I Reference Manual	B.5	BIT Representation
		BIT(8)		BIT(16)
	F-1-0 0-070 070~fl	0 0 0 0 0 0 0 0 1 T-00-07-0-0 070
		BIT(8)		BIT(16)
	F1_0 _10 _0 0_0 _0~	10000 000011010 00001
		BIT(8)		BIT(16)
		N/A	1 0011 010010001 007170]

Figure B-5. Bit-string Data Representation

B.6	POINTER Data

PL/I-80 and PL/I-86 R1.0 store variables that provide access to
memory addresses as two contiguous bytes. The low-order byte is
stored at the lowest memory address. POINTER data items appear as
LS	I 	MS

where LS denotes the least significant byte of the address, and MS
denotes the most significant byte.

B.7	ENTRY and LABEL Data

PL/I-80 and PL/I-86 R1.0 store ENTRY and LABEL data as two
contiguous bytes. The low-order byte is stored at the lowestmemory
address. ENTRY and LABEL data items appear as
I LS I MS7

where LS denotes the least significant byte of the address, and MS
denotes the most significant byte.

PL/I-86 Rl.l allocates 8 bytes for ENTRY and LABEL data items. The
8 bytes contain the following fields:
I Offsetl Code segment I stack Frame Istac
2	2	2	2

B.8	File Constant Representation

PL/I associates each file constant with a File Parameter Block
(FPB). The FPB occupies 57 contiguous bytes containing various
fields, some of which are implementation dependent.

B-10
PL/I Reference Manual	B.8 File Constant Representation

Note: each file declaration causes a static allocation for the
associated FPB. When you open the file, there is an additional
overhead for the operating system FCB and buffer space. The run
time system dynamically allocates this storage from the free storage
area.

BA Aggregate Storage

PL/I stores aggregate data items contiguously with no filler bytes.
Bit data is always stored unaligned, but each bit variable starts on
a new byte. Arrays are stored in row-major order, with the
rightmost subscript varying fastest.

For example, the declaration:
	declare A(2,2,2);
results in the following storage allocation:
11,1,11111,211,2,111,2,212,1,1 1 2,1,2 1 2,2,112,27,2
low 	high

End of Appendix B

B-11
	Appendix C
Interface Conventions

This appendix describes a standard set of conventions for
interfacing PL/I programs with assembly language routines and with
programs written in other high-level languages.

Note: in this section PL/I applies to both PL/I-80 and PL/I-86
unless otherwise indicated.

C.1 Parameter Passing Using a Parameter Block

You can pass parameters between a PL/I program and an assembly
language routine by loading a register pair with the address of a
Parameter Block containing pointer values. These pointers in turn
lead to the actual parameter values. The number of parameters and
the parameter length and type must be determined implicitly by
agreement between the calling program and called subroutine. Figure
C-1 illustrates the concept. The address fields are arbitrary.

Register Pair		Parameter Block	Parameters

HL (8080)		1000:	2000	a-2000:	parameter

	1000
i~ 	3000
BX (808b)	4000	3000:		parameter2

4000:		parameter 3

500

5000		parameter 71

Figure C-1. PL/1 Parameter Passing Mechanism

The following example illustrates this parameter passing mechanism.
Suppose a PL/I program uses a considerable number of floating-point
divide operations, where each division is by a power of two.
Suppose also that the iterative loop where the divisions occur is

C-1
PL/I Reference Manual	C.1 Using a Parameter Block

speed-critical, and that it is useful to have an assembly language
subroutine to perform the division.

The assembly language routine simply decreases the binary exponent
of the floating-point number for each power of two in the division.
Decreasing the exponent effectively performs the divide operation
without the overhead involved in unpacking the number, performing
the general division operation, and repacking the result. During
the division, the assembly language routine can produce underflow,
and must signal the UNDERFLOW condition to the PL/I program if this
occurs.

The following three listings show programs that demonstrate
parameter passing. Listing C-1 shows the program DTEST, which tests
the division operation. Listing C-2 shows DIV2.ASM, the 8080
assembly language subroutine that performs the division. On line 8,
DTEST defines DIV2 as an external entry constant with two
parameters: a FIXED(7) and a floating-point binary value. Listing
C-3 shows DIV2.A86, which is the same subroutine in 8086 assembly
language.

on each iteration of the DO-group, DTEST stores the test value 100
into f (line 13), and passes it to the DIV2 subroutine (line 14).
At each call to DIV2, DTEST changes the value of f to f/(2**i) and
prints it using a PUT statement. At the point of call, DIV2
receives two addresses that correspond to the two parameters i and
f.

Upon entry, DIV2 loads the value of i to the accumulator, and sets
the appropriate register pair to point to the exponent field of the
input floating-point number. If the exponent is zero, DIV2 returns
immediately, because the resulting value is zero.

Otherwise, the subroutine loops at the label dby2 while counting
down the exponent as the power of two diminishes to zero. If the
exponent reaches zero during this counting process, DIV2 signals the
UNDERFLOW condition.

In DIV2, the call to ?signal demonstrates the assembly language
format for parameters that use the interface. The ?signal
subroutine is part of the PL/I Run-time Subroutine Library (PLILIB) .

This subroutine loads the appropriate register pair with the address
of the Signal Parameter List, denoted by siglst. The Signal
Parameter List, in turn, is a Parameter Block of four addresses
leading to the signal code sigcode, the signal subcode sigsub, the
filename indicator sigfil (not used here) , and the auxiliary message
sigaux that is the last parameter.

The auxiliary message can provide additional information when an
error occurs. The signal subroutine prints the message until it
either exhausts the string length (32, in this case), or encounters
a binary 00 in the string.

C-2
PL/I Reference manual	C.1 Using a Parameter Block

Listing C-4 shows the abbreviated output from this test program.
The loop counter i becomes negative when it reaches 128, but the
DIV2 subroutine treats this value as an unsigned magnitude value;
thus UNDERFLOW occurs when i reaches -123.

1			a
2			a	/* This program tests an assembly language routine to
3			a	/* do floating-point division.
4			a
5			a 	dtest:
	6		b	procedure options(main);
	7		b	declare
	8		b		div2 entry(fixed(7),float),
	9		b		i fixed(7),
	10		b		f float;
	11		b
	12		c	do i = 0 by 1;
	13		c			f = 100;
	14		c			call div2(i,f);
	15		c			put skip list('100 / 2
	16		c	end;
	17 		b
18 bL- end dtest;

Listing C-1. The DTEST Program

C-3
PL/I Reference Manual	C.1 Using a Parameter Block

title	'division by power of two'
public	div2
extrn	?signal
entry:
pl - fixed(7) power of two
	p2 - floating-point number
	exit:
pl - (unchanged)
	p2	p2 / (2**pl)
div2:			;HL =	low(.pl)
	mov	e,m	;low(.Pl)
	inx	h	;HL =	high(.pl)
	mov	d,m	;DE =	pl
	inx	h	;HL =	low(p2)
	ldax	d	;a = pl (power of two)
	mov	e,m	;low(.p2)
	inx	h	;HL =	high(.p2)
	mov	d,m	;DE =	p2
	xchg		;HL = 	p2

A = power of 2, HL = low byte of fp num
inx	h	;to middle of mantissa
inx	h	;to high byte of mantissa
inx	h	;to exponent byte
inr	m
dcr	m	;p2 already zero?
rz		;return if so
dby2:	;divide by two
ora	a	;counted power of 2 to zero?
rz		;return if so
dcr	a	;count power of two down
dcr	m	;count exponent down
jnz	dby2	;loop again if no underflow

;underflow occurred, signal underflow condition
	lxi	h,siglst;signal parameter list
	call	?signal	;signal underflow
	ret		;normally, no return
	dseg
siglst:	dw	sigcod	;address of signal code
	dw	sigsub	;address of subcode
	dw	sigfil	;address of file code
	dw	sigaux	;address of aux message
end of parameter vector, start of params
sigcod:	db	3	;03 = underflow
sigsub:	db	128	;arbitrary subcode for id
sigfil:	dw	0000	;no associated file name
sigaux:	dw	undmsg	;0000 if no aux message
undmsg:	db	32,'Underflow in Divide by Two',O
	end

Listing C-2. DIV2.ASK Assembly Language Program (8080)

C-4
