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(ANEXT 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