Scope
The purpose of this article is to provide an example of PL/I programming so as to help people who are forced to
use this language (there is way they SELECTED by Free Will to start building things with PL1 in their home…) be productive from Day 1. The example is a program with “encrypts” and “decrypts” a text entered by the user.
I will walk through the readers through the program, so that they understand all the basic concepts and commands of this language.
About PL/I Language
The programming language known as PL/I or PL/1 (read “P L ONE”) is a proprietary language of IBM. Because of it being closed and due to unavailability of compilers out in the wild (other than those of IBM) the language did not become popular. It is now used in zOS Mainframe Core Baking Systems across various big banks in the world.
PL/I Compiler
Search http://www.tek-tips.com/viewthread.cfm?qid=1669923 to find a PL/I compiler for Windows. The compiler resides at ftp://ftp.software.ibm.com/ps/products/pli/demos/ and can be executed in Windows XP. So if you have Windows 7 or 8 or newer, you must download a Windows XP Virtual Machine (see Windows Virtual PC) in order to be able to execute it and write in PL/I.
After you have donwloaded it and have installed it into your XP Machine, use it as follows:
- Enter 'pli nameoftheprogram.pli' in order to compile
- Enter 'ilink nameoftheprogram.obj' to link to an executable file
The Program
The program has the following components.
1. Main Procedure: In this procedure the program asks from the user to select the mode of the program (encrypt / decrypt). It then asks from the user to enter the text to encrypt or decrypt and calls the relative internal procedures (functions) to perform the selected action. The output of the action is presented to the user and the program terminates.
Declare variables
SKAKOS1: PROC OPTIONS(MAIN) REORDER;
DCL ENCRYPT_KEY DEC(2) INIT (1);
DCL DECRYPT_KEY DEC(2) INIT (1);
DCL USER_TEXT CHAR(50) INIT (' ');
DCL RESULT CHAR(100) INIT (' ');
DCL HUO0 CHAR(1) INIT (' ');
DCL HUO1 CHAR(1) INIT (' ');
DCL EXECMODE FIXED DEC (1);
DCL STOPPROG FIXED DEC (1);
DCL I FIXED DEC (2);
ENCRYPT_KEY = 1;
DECRYPT_KEY = 1;
Program main procedure
DO I = 1 TO 25;
PUT SKIP LIST('');
END;
PUT SKIP LIST ('HUO ENCRYPTOR - CIA Version (128 bit)');
PUT SKIP LIST(' ');
PUT SKIP LIST('SELECT PROGRAM MODE (1 or 2)');
PUT SKIP LIST('----------------------------');
PUT SKIP LIST('OPTION 1: ENCRYPT');
PUT SKIP LIST('OPTION 2: DECRYPT');
PUT SKIP LIST(' ');
GET SKIP(0) LIST(EXECMODE);
PUT SKIP LIST(' ');
PUT SKIP LIST('ENTER TEXT:');
GET EDIT (USER_TEXT)(A(50));
IF (EXECMODE = 1) THEN
DO;
RESULT = ENCRYPT(USER_TEXT);
END;
ELSE IF (EXECMODE = 2) THEN
DO;
RESULT = DECRYPT(USER_TEXT);
END;
PUT SKIP LIST(' ');
PUT SKIP LIST ('RESULT: ' || RESULT);
PUT SKIP LIST ('--- PROGRAM TERMINATED ---');
2. Encrypt procedure: This is the function responsible for the encryption of data. It has as Input the text to encrypt and returns as Output the encrypted text.
The process of encryption is as follows:
- The reads the input string letter-by-letter
- It calls CHAR_TO_ASCII function to get the ASCII numerical value of the letter read. The CHAR_TO_ASCII function is described later on.
- It increased the ASCII value by the Encryption Key value
- It transforms the changed ASCII value to a character again via the ASCII_TO_CHAR function. The CHAR_TO_ASCII function is described later on.
- It puts the letter read to the Output string (until all letters of Input are processed).
ENCRYPT:PROC(INPUT_TEXT) RETURNS(CHAR(50));
DCL INPUT_TEXT CHAR(50);
DCL OUTPUT_TEXT CHAR(50);
DCL I DEC(2);
DCL HUO0 CHAR(1);
DCL HUO1 CHAR(1);
OUTPUT_TEXT = INPUT_TEXT;
DO I = 1 TO LENGTH(INPUT_TEXT);
HUO0 = SUBSTR(INPUT_TEXT,I,1);
IF HUO0 = ' ' THEN DO;
HUO1 = ' ';
END;
ELSE DO;
HUO1 = ASCII_TO_CHAR((CHAR_TO_ASCII(HUO0) + ENCRYPT_KEY));
END;
SUBSTR(OUTPUT_TEXT,I,1) = HUO1;
END;
RETURN(OUTPUT_TEXT);
END ENCRYPT;
3. Decrypt procedure: This is the function responsible for the decryption. It has the same logic as the Encrypt procedure, but it decreases the ASCII value of the letters (so as to perform the opposite operation than that of the Encrypt function).
DECRYPT:PROC(INPUT_TEXT) RETURNS(CHAR(50));
DCL INPUT_TEXT CHAR(50);
DCL OUTPUT_TEXT CHAR(50);
DCL I DEC(2);
DCL HUO0 CHAR(1);
DCL HUO1 CHAR(1);
OUTPUT_TEXT = INPUT_TEXT;
DO I = 1 TO LENGTH(INPUT_TEXT);
HUO0 = SUBSTR(INPUT_TEXT,I,1);
IF HUO0 = ' ' THEN DO;
HUO1 = ' ';
END;
ELSE DO;
HUO1 = ASCII_TO_CHAR((CHAR_TO_ASCII(HUO0) - DECRYPT_KEY));
END;
SUBSTR(OUTPUT_TEXT,I,1) = HUO1;
END ;
RETURN(OUTPUT_TEXT);
END DECRYPT;
4. CHAR_TO_ASCII procedure: This function has as input a letter (a character) and returns the ASCII numerical value responding to that specific letter. Note that the ASCII values are “home made” (defined by me and do not follow the official ASCII coding).
CHAR_TO_ASCII:PROC(INPUT_CHAR) RETURNS(DEC(2));
DCL INPUT_CHAR CHAR(1);
DCL OUTPUT_NUM DEC(2);
DCL DEBUG_NUM DEC(1);
SELECT (INPUT_CHAR);
WHEN ('A') OUTPUT_NUM = 1;
WHEN ('B') OUTPUT_NUM = 2;
WHEN ('C') OUTPUT_NUM = 3;
WHEN ('D') OUTPUT_NUM = 4;
WHEN ('E') OUTPUT_NUM = 5;
WHEN ('F') OUTPUT_NUM = 6;
WHEN ('G') OUTPUT_NUM = 7;
WHEN ('H') OUTPUT_NUM = 8;
WHEN ('I') OUTPUT_NUM = 9;
WHEN ('J') OUTPUT_NUM = 10;
WHEN ('K') OUTPUT_NUM = 11;
WHEN ('L') OUTPUT_NUM = 12;
WHEN ('M') OUTPUT_NUM = 13;
WHEN ('N') OUTPUT_NUM = 14;
WHEN ('O') OUTPUT_NUM = 15;
WHEN ('P') OUTPUT_NUM = 16;
WHEN ('Q') OUTPUT_NUM = 17;
WHEN ('R') OUTPUT_NUM = 18;
WHEN ('S') OUTPUT_NUM = 19;
WHEN ('T') OUTPUT_NUM = 20;
WHEN ('U') OUTPUT_NUM = 21;
WHEN ('V') OUTPUT_NUM = 22;
WHEN ('W') OUTPUT_NUM = 23;
WHEN ('X') OUTPUT_NUM = 24;
WHEN ('Y') OUTPUT_NUM = 25;
WHEN ('Z') OUTPUT_NUM = 26;
OTHERWISE OUTPUT_NUM = 99;
END;
RETURN(OUTPUT_NUM);
END CHAR_TO_ASCII;
5. ASCII_TO_CHAR procedure: This internal procedure performs the opposite function from the CHAR_TO_ASCII one. It returns the character representing a specific ASCII value.
ASCII_TO_CHAR:PROC(INPUT_ASCII) RETURNS(CHAR(1));
DCL INPUT_ASCII DEC(2);
DCL OUTPUT_CHAR CHAR(1);
IF INPUT_ASCII = 27 THEN DO;
INPUT_ASCII = 1;
END;
IF INPUT_ASCII < 0 THEN DO;
INPUT_ASCII = 26;
END;
SELECT (INPUT_ASCII);
WHEN (99) OUTPUT_CHAR = ' ';
WHEN (1) OUTPUT_CHAR = 'A';
WHEN (2) OUTPUT_CHAR = 'B';
WHEN (3) OUTPUT_CHAR = 'C';
WHEN (4) OUTPUT_CHAR = 'D';
WHEN (5) OUTPUT_CHAR = 'E';
WHEN (6) OUTPUT_CHAR = 'F';
WHEN (7) OUTPUT_CHAR = 'G';
WHEN (8) OUTPUT_CHAR = 'H';
WHEN (9) OUTPUT_CHAR = 'I';
WHEN (10) OUTPUT_CHAR = 'J';
WHEN (11) OUTPUT_CHAR = 'K';
WHEN (12) OUTPUT_CHAR = 'L';
WHEN (13) OUTPUT_CHAR = 'M';
WHEN (14) OUTPUT_CHAR = 'N';
WHEN (15) OUTPUT_CHAR = 'O';
WHEN (16) OUTPUT_CHAR = 'P';
WHEN (17) OUTPUT_CHAR = 'Q';
WHEN (18) OUTPUT_CHAR = 'R';
WHEN (19) OUTPUT_CHAR = 'S';
WHEN (20) OUTPUT_CHAR = 'T';
WHEN (21) OUTPUT_CHAR = 'U';
WHEN (22) OUTPUT_CHAR = 'V';
WHEN (23) OUTPUT_CHAR = 'U';
WHEN (24) OUTPUT_CHAR = 'X';
WHEN (25) OUTPUT_CHAR = 'Y';
WHEN (26) OUTPUT_CHAR = 'Z';
OTHERWISE OUTPUT_CHAR = ' ';
END;
RETURN(OUTPUT_CHAR);
END ASCII_TO_CHAR;
Program Flow
The flow of the program is basically this:
- Prompt user to select mode (Encrypt / Decrypt).
- Prompt the user to enter Text for processing.
- Call Encrypt or Decrypt procedure depending on what the user selected.
- Return the result of the operation on screen.
Additional concepts
PL/I is a very powerful language. Its use in Banking is mainly limited to “get data, process data, give data to output” kind of applications. These applications call for including the copybook of the used programs (via the %INCLUDE function), fill in the input of the program before you call it (via PROGRAM.IDATA.NAME = ‘SKAKOS’; type of commands), call the program (usually with a MACRO specific to each architecture) and then handle the returned result from the program.
Happy (?) coding!
END;
Related PL/I Links
History
Initial Version - 27/11/2012