# - THE PL/I NEWSLETTER -

ISSUE NO. 7 – DECEMBER 2003

IN THIS ISSUE:
1. Editorial
2. Introduction to the Windows Header Files for IBM VisualAge PL/I for Windows, by Mark Yudkin
3. PL/I in an Easy Lesson
4. iSUB, by Robin Vowels
5. Announcements
• GCC front-end for the PL/I programming language, by Henrik Sorensen
• Update PL/I kit for Alpha OpenVMS, by Tom Linden
6. The new Built-in Functions of IBM Enterprise PL/I, by Robin Vowels
7. Usefulle Webbe Lynx ...
8. Current IBM PL/I offerings in the U.S.
9. Cool Codes

2. ## Introduction to the Windows Header Files for IBM VisualAge PL/I for Windows

by Mark Yudkin

3. ## PL/I in an Easy Lesson

- something for everyone!
4. ## iSUB

iSUB may be used to simplify some operations involving arrays.
iSUB may be used to define two or more arrays that share the same storage.

For example, suppose a square matrix A exists of size 10 × 10. We may specify a second array D of size 10 that references only those elements on the diagonal. The declaration is:

DECLARE A(10,10) FLOAT, D(10) DEFINED A(1SUB, 1SUB) FLOAT; Thus PUT (D); will print only the diagonal elements of A.

In another instance, suppose a matrix has zero elements everywhere except for those on the diagonal. iSUB may be used in such a way that only those diagonal elements are held in storage, with a considerable saving in storage. However, iSUB allows that matrix to be referenced as if all elements (including the zero elements) were held in storage.

The next example declaration reserves storage for the diagonal elements and provides the means to reference all elements of the matrix B.

DECLARE A(11) FLOAT INITIAL (7, 5, 8, 2, 6, 1, 4, 9, 3, 10, 0), B(10,10) DEFINED A(1SUB*(1SUB=2SUB) + (1SUB^=2SUB)*HBOUND(A) ) FLOAT; In the example, the 10 elements on the diagonal are stored in a(1) to A(10), and one zero element is stored in A(11). This latter element is accessed whenever a reference is made to an off-diagonal element.

The statement PUT (A); will print only 11 elements, while the statement PUT (B); will print all 100 elements of the matrix. But note that only 11 elements of the matrix are stored.

The following declaration will allow access to elements of the other diagonal (from the top right-hand corner to the bottom left-hand corner).

DECLARE A(10,10) FLOAT, D(10) DEFINED A(1SUB, HBOUND(A)-1SUB+1) FLOAT; Symmetric Matrix

In a symmetric matrix, the elements above the diagonal are the mirror image of those below the diagonal. In other words, element A(i,j) = A(j,i) for all i ^= j.

Under these circumstances, only the diagonal elements and all those below the diagonal need to be stored. For an n × n matrix, the storage required is n(n-1)/2 elements (or just over one-half the number of elements in the full matrix.

We may therefore define a vector consisting of n(n-1)/2 elements, and we may define an n × n matrix that accesses those elements. This is possible because the position of an element (i,j) is given by the formula i*(i-1)/2+j. Thus:

DECLARE S(N*(N-1)/2) FLOAT, A(N,N) DEFINED B(1SUB*(1SUB-1)/2+2SUB) FLOAT; Thus a reference to element A(i,j) is translated to a reference to S(i*(i-1)/2+j).

This declaration permits the matrix A to be referenced by A(i,j) provided that i <= j.

An alternative declaration is required when the the diagonal and those elements above it are stored instead. This requires a more involved formula.

DECLARE S(N*(N-1)/2) FLOAT, A(N,N) DEFINED B(N*(1SUB-1)-1SUB*(1SUB-1)/2+2SUB) FLOAT; This declaration permits the matrix A to be referenced by A(i,j) provided that i >= j.

For both declarations, however, the formula needs to be modified if all elements of the matrix A are to be referenced (that is, if A(i,j) is to be used for all values of i and j.

The declaration for the lower triangular form thus becomes:

DECLARE S(N*(N-1)/2) FLOAT, A(N,N) DEFINED B( (1SUB*(1SUB-1)/2+2SUB)*(1SUB <= 2SUB) + (2SUB+(2SUB-1)/2+1SUB)*(1SUB >= 2SUB) ) FLOAT; In all cases above where division by 2 is required, ISRL may be used instead (provided that n > 1).

Upper Triangular Matrix

If the matrix is upper triangular (that is, all elements below the diagonal are zero), the following declaration may be used to define storage for the matrix:

DECLARE S(N*(N-1)/2) FLOAT, A(N,N) DEFINED B (N*(1SUB-1)-1SUB*(1SUB-1)/2 + 2SUB) FLOAT; (Fike, p. 58)
The elements A(i,j) stored may be referenced for all values of i and j such that i <= j. That means that the user may need to include a test to avoid referencing any element below the diagonal (which would, of course, be zero).

If it is desired to reference all elements of the array -- including the zero-valued elements beneath the diagonal, the following declaration and assignment would be required:

DECLARE S(ISRL(N*(N-1),1)+1) FLOAT, A(N,N) DEFINED B( (N*(1SUB-1)-1SUB*(1SUB-1)/2 + 2SUB)*(1SUB <= 2SUB) + N*(1SUB>2SUB) ) FLOAT; A(N) = 0;

Submatrix

An interesting application is to define a sub-matrix. Consider the declaration

DECLARE A(N,N) FLOAT, Submatrix (N-2,N-2) DEFINED A(1SUB+1,2SUB+1) FLOAT; This declaration causes B to be the same as matrix A except that the first and last rows are missing, and the first and last columns are missing. Thus, if matrix A is - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Then matrix B is - 7 8 9 12 13 14

Cyclic Shift

To perform a cyclic shift or rotation of the elements of a matrix, the following declaration would suffice. This declaration assumes that the number of shifts is held in the variable Shift.

DECLARE A (M,N) FLOAT(18), B (M,N) DEFINED A(LBOUND(A,1)+MOD(1SUB-Shift-LBOUND(A,1), HBOUND(A,1)-LBOUND(A,1)+1),2SUB) FLOAT (18); Given that matrix A is: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 Then if Shift = 1, all rows of B are as if rows of A are shifted up by one row (the top row re-appears at the bottom). B appears as: 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 If Shift = -1, B is the same as A, but with all rows shifted down by one row (the bottom row appears at the top. B appears as: 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 In each case, the shifted array is obtained without actually shifting any rows of matrix A, with some savings in execution time.

Other possibilities include obtaining the elements of a vector in reverse order:

DECLARE V(N) FLOAT, W DEFINED V(N - 1SUB + 1) FLOAT; If V is the array 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, then W is the array 10 9 8 7 6 5 4 3 2 1.

References:

C. T. Fike, PL/I for Scientific Programmers, Prentice-Hall, Englewood Cliffs, N. J., 1970, pp. 57-58, 125.
IBM, OS/2 PL/I Version 2 Programming: Language Reference, 3rd Ed., ref. SC26-4308-2, 1990, pp. 160-164.
IBM, Enterprise PL/I for z/OS amd OS/390 Language Reference, Version 3 Release 1.0, 3rd Ed., ref. SC27-1460-00, 2001, pp. 260-264.

5. ## Announcements

1. GCC front-end for the PL/I programming language, by Henrik Sorensen, 17 Dec 2003
Some time ago an open source project was started with the goal to create a free PL/I compiler. The project moves slowly but surely forward. Currently a scanner and parser has been integrated into the build system of the GNU Compiler Collection (gcc). The integration into the gcc build system was non trivial, and would not have been possible without the help of the sample language Treelang by Tim Josling.
The GCC PL/I 0.0.2 release follows the syntax of IBM OS PL/I Version 2.
PL/I for GCC is released under the terms of the GNU Public License; version 2.
The pl1gcc v0.0.2, contains integration into gcc build system, plus a scanner and parser.
As you can tell, there is still a long way to go before any code generation is done.
Looking forward to see you there.
2. Update PL/I kit for Alpha OpenVMS, by Tom Linden, 12 December 2003.
An update kit is now available which may be downloaded from http://www.kednos.com
Also NEW is the documentation in BookReader, Postscript, Acrobat and HTML formats.
For more info, see the release notes available on the web site.

6. ## The new Built-in Functions of IBM Enterprise PL/I

by Robin Vowels

• CS The function reference CS (old, current, new) compares the fixed binary(31) values pointed at by old and current. If they are equal, the function returns zero, otherwise the value pointed at by old is replaced by fixed binary (31) value new and 1 is returned.
"The purpose is (I believe) to execute a hardware CS (Compare and Swap) instruction, which is guaranteed to do the compare and (optionally) the swap as an atomic operation, making it useful for implementing semaphores, etc. in multi-threaded code." (Peter Flass)
• LOWERCASE returns the lower-case version of the string argument.
• UPPERCASE returns the upper-case version of the string argument.
• PLIDUMP produces a formatted dump of storage used by the program.
For a detailed description (including details of arguments that specify the content of the dump), see Chapter 17 of IBM, Enterprise PL/I for z/OS and OS/390 Programming Guide Version 3 Release 1.0, 3rd Ed., San Jose, CA, 2001, ref., SC27-1457-00, pp. 348-350.
• PLISAXA and PLISAXB invoke the high-speed XML parser. Subroutine PLISAXA process an XML document held in memory, while subroutine PLISAXB processes a file of XML data.

The calling sequences are:
CALL PLISAXA (event_structure, pointer_value, buffer_address, n);
CALL PLISAXA (event_structure, pointer_value, buffer_address, n, code_page);
pointer_value is passed back by the XML parser.
n is the number of bytes in the buffer (if WIDECHAR data is used, n is twice the length of the string reported by LENGTH).
ADDRDATA must be used when the buffer is VARYING.

The calling sequences are:
CALL PLISAXB (event_structure, pointer_value, file);
CALL PLISAXB (event_structure, pointer_value, file, code_page);
Supports 21 EBCDIC code pages and 3 ASCII code pages.
For a detailed description (including examples and details of the supported code pages and error messages and their explanations), see Chapter 16 of IBM, Enterprise PL/I for z/OS and OS/390 Programming Guide Version 3 Release 1.0, 3rd Ed., San Jose, CA, 2001, ref., SC27-1457-00, pp. 323-347.

7. ## Usefulle Webbe Lynx ...

Peter Flass is building a resource at: Peter Flass's PL/I home page.

8. ## Current IBM PL/I offerings in the U.S.

IBM has enhanced VisualAge® PL/I with powerful features to increase development productivity, simplify the maintenance of your legacy code, and provide seamless portability from your host to your workstation. It also provides the tools needed to identify your Year 2000 date-related fields on both OS/2 and Windows NT.

VisualAge PL/I Enterprise Edition Version 2.1 combines the two separate offerings from the previous release of VisualAge PL/I (Standard and Professional) into a single offering available on both the OS/2 and Windows NT platforms. By doing so, it provides these productivity features:

• remote edit/compile
• redevelopment tools
• cross platform development
• year 2000 assessment strategies, find and fix, and test capabilities

Also included as an extra bonus offering is VisualAge CICS® Enterprise Application Development, which enables CICS host application development on the workstation.

• Product number 04L6564: VisualAge PL/1 Enterprise V2.1
• 04L6565: VisualAge PL/I Enterprise V2.1 Upgrade from Prior IBM PL/I Workstation or Competitive Products Program Package CD-ROM
• 04L6567: VisualAge PL/I Enterprise V2.1 Upgrade from Professional V2.0 Program Package CD-ROM
• 04L6566: VisualAge PL/I Enterprise V2.1 Upgrade from Standard V2.0 Package CD-ROM

9. ## Cool Codes

by Robin Vowels

To display a progress summary on the same line on the PC screen, use the following:

DCL ESC CHARACTER(1) INITIAL ('1B'X); PUT SKIP EDIT ('Completed ', K, '%', ESC, '[1A' ) (A, F(3), 2 A); To accept a password from the keyboard (without displaying it on the screen), use the following: declare ESC character (1) initial ('1B'x); declare password character (20) varying initial (''); put edit (ESC, '[8m') (A); get edit (password) (L); put edit (ESC, '[0m') (A); As each keystroke is made, the cursor moves along the screen.

You will neeed to have ANSI.SYS loaded.