您的当前位置:首页正文

RPG AS400程序员培训手册6

2022-02-01 来源:步旅网


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 的效果,同时该项参数高亮显示。试一试

就知道了

因篇幅问题不能全部显示,请点此查看更多更全内容