5 CL、CMD
其实有关这一章,以及屏幕文件的,在网上已经有很多人写过了,想了想,还是说一下吧。
5.1 CL 程序
5.1.1 基本认识
简单的理解,CL 程序就是和RPG 相对应的,是控制语言(Control Language)。类型为
CLP、CLLE 的源代码编译出来的程序,都属于CL 程序。
可能还是不够直观,这么说吧,我们在交互式命令行上输入的命令,用程序的方式来执
行,这个执行的程序,就是CL 程序。
学过UNIX 的会比较好懂,CL 程序有点类似于SHELL,不过SHELL 是可以直接执行
的,而且不用编译;CL 程序需要编译,而且要用CALL 的方式来执行。不过原理是接近的,
都是在程序中直接调用命令行的语句。
所以说,CL 程序其实很好写,只要会输入命令,就可以写CL 程序了。在编辑CL 程
序时,也可以用“命令 + F4”的方式来写,不需要老老实实的整行输入。
CL 程序不像RPGLE 程序,在编写时,可以使用自由格式书写;一行的内容如果太长
要,在最末尾处用“+”表示换行
举个最简单的例子,比如说新建个名为FHS01CL 的CLP 源程序,代码如下:
PGM
WRKACTJOB
ENDPGM
编译此程序,然后CALL 之,系统就会执行命令WRKACTJOB,查看当前的活动作业,
效果与在交互式命令行下输入WRKACTJOB 是一样的。
当我们输入F12,退出WRKACTJOB 时,系统就会继续向下执行,发现是ENDPGM,
表示程序结束了,于是判定执行完毕,退出至交互式画面。
5.1.2 CL 程序的常用语法及命令:
一、程序的开始与结束:
PGM PARM(&A &B) /* 开始CL 程序 */
ENDPGM /* 结束CL 程序 */
CL 程序,和RPGLE 程序一样,也可以有程序的入口参数,而且程序的入口参数
都是可传递的(也就是输入的参数如果在程序中被修改过,那么原调用的程序中的相应
参数也会进行变化。不过CL 的入口参数只能为字符型,或数字型的单个字段,不能象
RPGLE 程序中那么多样化(字段、结构、数组、指针)。
如果CL 程序没有入口参数时,那么就可以不需要后面的PARM 语句,直接写成
PGM
即可。
写CL 程序时,不妨多使用F4,看看系统的帮助,这样就不用记那么多命令的参
数名。
二、变量及其定义
CL程序中的所有变量,都使用&做为前缀,这一点与RPGLE 程序不同。比如说
PGM PARM(&A &B)
就表示入口参数为A、B 这两个变量
在CL 程序中使用到的变量,都必须使用DCL 语句来定义:
DCL VAR(&FLD01) TYPE(*CHAR) LEN(10)
DCL VAR(&FLD02) TYPE(*DEC) LEN(10 2)
上述语句表示:
定义变量FLD01,10 位长的字符型变量
定义变量FLD02,10 长,其中2 位小数的数字型变量
除了字符、数字之外,CL 程序还可以定义逻辑变量(*LGL),逻辑变量允许的值只
能为’1’或’0’。不过通常有字符与数字也就够了。CL 程序的主要功能在于进行命令处理,
而不是处理字符串以及数据库
三、CL 常用命令:
CHGVAR -- 变量赋值
CHGVAR VAR(&FLD01) VALUE(‘ABCD’)
即是将变量FLD01 赋值成为’ABCD’(左对齐), 同理,VALUE 的括号中也可
以填写一个变量,即表示将此变量的值赋值到变量FLD01 中。
数字型变量的赋值同样也是使用CHGVAR 语句。
当变量中只包含数字时(0—9),数字型变量与字符型变量可以使用CHGVAR
语句进行转换,这一点与RPGLE 中的MOVE 语句比较类似。
IF -- 条件判断语句
IF COND(&FLD01 *EQ '1') THEN(CHGVAR VAR(&FLD02) +
VALUE('0'))
当变量FLD01 等于’1’时,将变量FLD02 中的值更改为’0’
THEN 后面,即是当符合条件时,要执行的命令。写起来其实没有看上去那么
复杂,多用F4 就会发现CL 程序写简单。
就比如上例,先写IF,然后按F4,在Condition 处填写条件语句,然后在
Command 处填上CHGVAR,再按F4,再去填相应的处理语句,这样写,就比直
接把整句抄下来就简单多了。
上面这种写法,只能在符合条件时,执行一条CL 语句;如果要执行多条,就
必须写做:
IF COND(&FLD01 *EQ '1') THEN(DO)
CHGVAR VAR(&FLD02) VALUE(‘0’)
其它执行语句
ENDDO
也就是THEN 后面,用DO,表示接下来的语句都是在这个IF 条件成立时才
执行(DO)的。
然后结束处用ENDDO,必须要有。ENDDO 在这里和循环没有任何关系,表
示的是ENDIF 的意思,但是CL 语句里没有ENDIF,只有ENDDO。
IF 语句中,表示判断的关键字与RPGLE 中的Ifxx 操作码类似,有
*EQ *GT *LT *GE *LE *NE
用来表示逻辑关系的关键字有
*AND, *OR, *NOT
GOTO -- 跳转语句
GOTO 语句与RPGLE 中的GOTO 是一样的,都是跳转的意思。
FHSTAG:
GOTO CMDLBL(FHSTAG)
注意,这里定义标签是用“:” 冒号
MONMSG -- 监控错误信息
我们使用CL 语句时,执行的命令可能会报出一些异常错误,从而导致整个程
序中断,需要手工干预。MONMSG 命令可以监控我们预定的错误信息,使CL 程
序正常的向下运行。举例而言,如果CL 程序中有如下语句:
CALL PGM(FHS01R)
MONMSG MSGID(CPF4131)
则表示当系统调用程序FHS01R 时,如果发现有CPF4131(声明的文件重新编
译过,但程序未重新编译)的错,那么CL 程序将不会异常中断,仅仅只是不运行
程序FHS01R,然后继续向下执行CL 程序
MONMSG 还可以用于在监控到错误信息之后,进行处理,如下:
CALL PGM(FHS01R)
MONMSG MSGID(CPF4131) EXEC(CHGVAR VAR(&FLD01) +
VALUE('0'))
这句话就表示当发现有CPF4131 的错误之时,将变量FLD01 赋值成为’0’如果要执行多句的话,和IF 语句的方法类似,也是使用DO 与ENDDO MONMSG MSGID(CPF4131) EXEC(DO)
CHGVAR VAR(&FLD01) VALUE(‘0’)
其它处理语句
ENDDO
5.1.3 不常用的语法
%SST -- 取字符串
CHGVAR VAR(&FLD01) VALUE(%SST(&FLD02 3 1))
表示将字符变量FLD02,从第3 位开始,取1 位,左对齐赋值到变量FLD01 中。
%SST 的括号的参数中,第一个参数必须为字符型变量,第二个参数表示起始位,
第三个参数表示要截取的长度。
*CAT -- 拼字符串
DCL VAR(&FLD01) TYPE(*CHAR) LEN(10)
CHGVAR VAR(&FLD01) VALUE('A' *CAT 'B')
即表示将10 位长的字符型变量赋值成为’AB ‘
‘A’, ‘B’,也可以使用变量,如
CHGVAR VAR(&FLD01) VALUE(&FLD02 *CAT &FLD03)
要注意,*CAT 不能去掉字符串末尾的空,从效果上来看,有点类似于RPGLE 中
的EVAL 操作码,而不是CAT 操作码
+、-、*、/ -- 数学运算
数字型变量,可以进行数学运算
CHGVAR VAR(&FLD01) VALUE(&FLD01 + &FLD02)
即等同于RPGLE 程序中的 EVAL FLD01 = FLD01 + FLD02
同理,-、*、/ 分别对应减、乘、除
不过数学运行常用于RPGLE 程序中,较少用在CL 控制里面,这里只是介绍一下。
读取文件:(From Cuer:P1421)
DCL VAR(&FLD01) TYPE(*CHAR) LEN(2)
DCLF FILE(FHSLIB/PFFHS)
RCVF
CHGVAR VAR(&FLD01) VALUE(&FHS01)
以上这段CL 的意思,就是在CL 程序中读取PFFHS 文件,然后将读到的第一条记
录赋值到CL 的临时变量FLD01 中。
如果要将一个文件从头读到尾,则可以用如下语句来实现:
DCLF FILE(FHSLIB/PFFHS)
LOOP:
RCVF
MONMSG MSGID(CPF0864) EXEC(GOTO CMDLBL(EXIT))
读取到每条记录后的处理语句
GOTO CMDLBL(LOOP)
EXIT:
也就是说,信息CPF0864,即表示未读取到记录。
在CL 程序中声明文件使用DCLF 语句,一个CL 文件中只能声明一个文件,声明
语句必须在CL 控制语句之前。
使用声明的文件中的字段,同样需要在字段名前加上“&” ;
CL 程序中,无法控制游标,无法对记录进行定位操作。所以CL 程序对文件的操
作是比较弱的,通常我最多只用来读取某些只含少量记录的参数文件。
5.2 CMD
CMD 是用来生成命令的,执行后可以像其它系统命令一样,直接输入命令,或是F4,
不需要像CLP 一样,要CALL 一下。
其实CMD 本质上也是执行CLP 或RPGLE(在编译时指定),用起来,无非就是好看点,
直接一些,除此之外的意义,似乎也就没什么了。
举个例子,比如我们查看一个文件中的内容时,可以使用SQL 来查看,也可以使用命
令RUNQRY 命令来实现(RUNQRY QRYFILE(文件名))。但在我们要频繁查看文件
时,这两种方式似乎都不是很爽,也就是说要输入的内容都不是最少的,那我们可以设计一
个CMD,譬如说叫SEE,希望实现的最终效果,是在命令行输入“SEE 文件名”,就
可以查看PF 文件中的记录。那么,我们按如下步骤来实现:
1. 建立一个CLP 程序,比如叫SEECLP,代码如下
PGM PARM(&FILENAME)
RUNQRY QRYFILE(&FILENAME)
ENDPGM
2. 编译此程序
3. 建立一个CMD 程序(即源代码的属性为CMD),代码如下:
CMD PROMPT(' 显示文件记录 ')
PARM KWD(NAME) TYPE(*CHAR) LEN(10) MIN(1) +
CHOICE(' 显示文件记录内容 ') +
PROMPT('Display file record')
4. 编译此CMD,用F4,可见如下画面:
Create Command (CRTCMD)
Type choices, press Enter.
Command . . . . . . . . . . . . > SEE Name
Library . . . . . . . . . . . > FHSLIB Name, *CURLIB
Program to process command . . . > SEE Name, *REXX
Library . . . . . . . . . . . > *LIBL Name, *LIBL, *CURLIB
Source file . . . . . . . . . . > FHSFILE Name
Library . . . . . . . . . . . > FHSLIB Name, *LIBL, *CURLIB
Source member . . . . . . . . . > SEE Name, *CMD
Threadsafe . . . . . . . . . . . *NO *YES, *NO, *COND
其中,蓝色字体显示的,就是我们需要输入这个CMD 要调用的程序名(默认值与
CMD同名),这里我们将此项内容填为SEECLP,表示SEE 这个CMD,调用的是SEECLP
这个程序
5. 编译成功之后,我们在命令行执行“SEE 文件名” ,就可以看到指定文件的
记录。也可以用SEE + F4 的方式来使用
6. 要注意,CMD 中,PARM 表示的就是CMD 命令的参数,参数的个数、类型、长
度都必须与其调用的程序相匹配,但名称可以与其调用的程序中的参数名称不一
样,而且名称前面不能有“&”字符。
7. 在PARM 参数中,MIN(1),表示该项参数必须有值(即最小的有效长度为1),当
参数无值时,将会自动出现SEE + F4 的效果,同时该项参数高亮显示。试一试
就知道了
因篇幅问题不能全部显示,请点此查看更多更全内容