PL/I 教程 – 基本加密示例
基于加密示例的 PL/I 基本概念教程

范围
本文的目的是提供 PL/I 编程的示例,以帮助那些不得不
使用这种语言的人(没有人会自愿选择使用 PL1 在家里构建东西……)从第一天起就富有成效。 该示例是一个“加密”和“解密”用户输入的文本的程序。 
我将带领读者了解该程序,以便他们理解这种语言的所有基本概念和命令。
关于 PL/I 语言
编程语言 PL/I 或 PL/1(读作“P L ONE”)是 IBM 的专有语言。 由于它是封闭的,并且在野外无法获得编译器(除了 IBM 的编译器之外),该语言并没有流行起来。 现在它被用于世界各地各大银行的 zOS 大型机核心银行系统中。
PL/I 编译器
搜索 http://www.tek-tips.com/viewthread.cfm?qid=1669923 以查找 Windows 的 PL/I 编译器。 该编译器位于 ftp://ftp.software.ibm.com/ps/products/pli/demos/ 并且可以在 Windows XP 中执行。 因此,如果您有 Windows 7 或 8 或更新的版本,您必须下载 Windows XP 虚拟机(参见 Windows Virtual PC)才能执行它并用 PL/I 编写程序。

下载并安装到 XP 机器后,请按如下方式使用它
- 输入 'pli nameoftheprogram.pli' 以进行编译
- 输入 'ilink nameoftheprogram.obj' 以链接到可执行文件
程序
该程序具有以下组件。
1. 主程序:在此过程中,程序要求用户选择程序的模式(加密/解密)。 然后,它要求用户输入要加密或解密的文本,并调用相关的内部程序(函数)来执行所选的操作。 操作的输出呈现给用户,并且程序终止。
声明变量
	/* PROCEDURE ENCRYPTOR  */
 
	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; 
程序主程序
	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. 加密程序:这是负责数据加密的函数。 它将要加密的文本作为输入,并返回加密的文本作为输出。
加密过程如下:
- 按字母顺序读取输入字符串
- 它调用 CHAR_TO_ASCII 函数以获取所读取字母的 ASCII 数值。 CHAR_TO_ASCII 函数将在稍后描述。
- 它将 ASCII 值增加加密密钥值
- 它通过 ASCII_TO_CHAR 函数再次将更改后的 ASCII 值转换为字符。 CHAR_TO_ASCII 函数将在稍后描述。
- 它将读取的字母放入输出字符串中(直到处理完输入的所有字母)。
	/*-------------------------------------------------------*/
	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;
		/*PUT SKIP LIST('INPUT LENGTH: ',LENGTH(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;
		   /*PUT SKIP LIST('I = ' || I);*/
		END;
		RETURN(OUTPUT_TEXT);
	END ENCRYPT;
	/*-------------------------------------------------------*/ 
3. 解密程序:这是负责解密的函数。 它的逻辑与加密程序相同,但是它会减小字母的 ASCII 值(以便执行与加密函数相反的操作)。
	/*-------------------------------------------------------*/
	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 程序:此函数将一个字母(字符)作为输入,并返回对应于该特定字母的 ASCII 数值。 请注意,ASCII 值是“自制的”(由我定义,不遵循官方的 ASCII 编码)。
	/*-------------------------------------------------------*/
	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;
		/*PUT SKIP LIST('DEBUG CHECKPOINT 4');*/
		RETURN(OUTPUT_NUM);
        END CHAR_TO_ASCII;
	/*-------------------------------------------------------*/ 
5. ASCII_TO_CHAR 程序:此内部程序执行与 CHAR_TO_ASCII 程序相反的功能。 它返回代表特定 ASCII 值的字符。
	/*-------------------------------------------------------*/
	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;
	/*-------------------------------------------------------*/  
程序流程
该程序的流程基本上是这样的:
- 提示用户选择模式(加密/解密)。
- 提示用户输入要处理的文本。
- 根据用户选择的内容调用加密或解密程序。
- 在屏幕上返回操作结果。

其他概念
PL/I 是一种非常强大的语言。 它在银行业中的使用主要局限于“获取数据,处理数据,将数据提供给输出”之类的应用程序。 这些应用程序需要包含所用程序的 copybook(通过 %INCLUDE 函数),在调用程序之前填写程序的输入(通过 PROGRAM.IDATA.NAME = 'SKAKOS'; 类型的命令),调用程序(通常使用特定于每个架构的 MACRO),然后处理程序返回的结果。
祝您编码愉快(?)。
结束;
相关 PL/I 链接
- http://www.softpanorama.info/Lang/pl1.shtml
- http://www.angelfire.com/folk/anoop/pl-1.pdf
- http://www.scribd.com/doc/50157776/VisualAge-PLI-Programming-Guide-ver-2-1
- http://publib.boulder.ibm.com/infocenter/comphelp/v7v91/index.jsp?topic=/com.ibm.aix.pli.doc/ibmx2mst138.htm
- http://members.dodo.com.au/robin51/pliwhat.htm
- http://www.tek-tips.com/viewthread.cfm?qid=1669923
- http://www.csimn.com/CSI_pages/PLI_1.html
- http://mainframe230.blogspot.gr/2010/11/pli-sample-programs-3.html
- http://documentation.microfocus.com:8080/help/index.jsp?topic=%2Fcom.microfocus.eclipse.infocenter.enterprisedeveloper.vs%2FBKPFPFPREF.html
- ftp://ftp.software.ibm.com/ps/products/pli/demos/
历史
初始版本 - 2012/11/27



