分类:
2006-05-29 14:42:06
下面是%BIN的例子:
DCL VAR(&B2) TYPE(*CHAR) LEN(2) VALUE(X'001C')
DCL VAR(&N) TYPE(*DEC) LEN(3 0)
CHGVAR &N %BINARY(&B2)
变量&B2的内容看作二字节的二进整数,转换成十进等值为28。然后分配给十进变量&N。
DCL VAR(&N) TYPE(*DEC) LEN(5 0) VALUE(107)
DCL VAR(&B4) TYPE(*CHAR) LEN(4)
CHGVAR %BIN(&B4) &N
十进变量&N转换成4字节的二进数,并放在字符变量&B4中,&B4的值将 X‘0000006B’。
DCL VAR(&P) TYPE(*CHAR) LEN(100)
DCL VAR(&L) TYPE(*DEC) LEN(5 0)
CHGVAR &L VALUE(%BIN(&P 1 2) * 5)
变量&P的头两个字符看作二进整数。转换成它的十进等值,再乘以5,结果放在数字变量&L中。
DCL VAR(&X) TYPE(*CHAR) LEN(50)
CHGVAR %BINARY(&X 15 2) VALUE(122.56)
数122.56截取为整数122,然后转换为2字节二进整数,放在字符变量&X的15位和16位上,则&X的15位和16位中包括X‘007A’。
DCL VAR(&B4) TYPE(*CHAR) LEN(4)
CHGVAR %BIN(&B4) VALUE(-57)
值-57转换为4字节二进整数,然后分配给字符变量&B4。&B4中将是X‘FFFFFFC7’。
DCL VAR(&B2) TYPE(*CHAR) LEN(2) VALUE(X'FF1B')
DCL VAR(&C5) TYPE(*CHAR) LEN(5)
CHGVAR &C5 %BINARY(&B2)
&B2的内容看作2字节二进整数,并转换成它的十进等量-229。这个数被转换成字符放在&C5中,&C5中将是‘-0029&csq’。
DCL VAR(&C5) TYPE(*CHAR) LEN(5) VALUE(' 1253')
DCL VAR(&B2) TYPE(*CHAR) LEN(2)
CHGVAR %BINARY(&B2) VALUE(&C5)
&C5中的字符1253转换成十进制数,然后转换为二字节二进整数且存在&B2中,&B2中将是X‘04E5’。
DCL VAR(&S) TYPE(*CHAR) LEN(100)
IF (%BIN(&S 1 2) > 10)
THEN( SNDPGMMSG MSG('Too many in list.') )
&S的头两个字节看作是一个二进整数与10比较。如果它的值大于10,则执行SNDPGMMSG。
DCL VAR(&RTNV) TYPE(*CHAR) LEN(4)
CALLPRC PRC(PROCA) RTNVAL(%BIN(&RTNV 1 4))
过程PROCA返回一个4字节整数存在&RTNV中。
2.5.8 用%SUBSTRING内部函数
字串内部函数(%SST)产生一个已有字符串的子串,它仅能用在CL过程中。在CHGVAR中,%SST也能规定修改后变量放在哪儿(VAR参数),或变量修改后的值(VALUE参数)在IF命令中,%SST也能在表达式中规定。
%SST的格式为:
%SUBSTRING(字符变量名 起始位 长度)
或%SST(字符变量名 起始位 长度)
可用*LDA做字符变量名指出%SST在本地数据区中取子串。子串功能从规定的CL字符变量或本地数据区中取子串,子串从‘超始位’开始取(它可以是一个变量名),继续到规定的长度(也可为一个变量名)。
起始位、长度不能是0和负数。如果起始位和子串长的和大于整个变量的长度,则出
错,本地数据区的长度为1024。
下面是子串的例子:
如果字符变量&NAME的头两位是IN,则调用INV210。&NAME的整个值传送给INV210。而&ERRCODE不变。否则,它的值为99。
DCL &NAME *CHAR VALUE(INVOICE)
DCL &ERRCODE *DEC (2 0)
IF (%SST(&NAME 1 2) *EQ 'IN') +
THEN(CALL INV210 &NAME)
ELSE CHGVAR &ERRCODE 99
如果&A的头两位与&B的头两位匹配,则调用CUS210:
DCL &A *CHAR VALUE(ABC)
DCL &B *CHAR VALUE(DEF)
IF (%SST(&A 1 2) *EQ %SUBSTRING(&B 1 2)) +
CALL CUS210
位置和长度也可以是变量。下例修改变量&X中从位置&Y开始长度为&2的内容为123。
CHGVAR %SST(&X &Y &Z) '123'
在命令运行前&A为ABCDEFG。在运行下列命令后,&A为A123EFG:
CHGVAR %SST(&A 2 3) '123'
在下例中,子串的长度5给出与之比较的操作数YES的长度。操作数要填零以便能比较YESNO与YESbb,条件为假。
DCL VAR(&NAME) TYPE(*CHAR) LEN(5) VALUE(YESNO)
.
.
.
IF (%SST (&NAME 1 5) *EQ YES) +
THEN(CALL PROGA)
如果子串比操作数短,子串要填空格做比较,例如:
DCL VAR(&NAME) TYPE(*CHAR) LEN(5) VALUE(YESNO)
.
.
.
IF (%SST(&NAME 1 3 ) *EQ YESNO) THEN(CALL PROG)
由于YESbb不等于YESNO,故条件为假。
下例中,变量&A的值放到本地数据区的1—10位上。
CHGVAR %SST(*LDA 1 10) &A
如果本地数据区的1—3位与常量‘XY2’连接后等于变量&A,则调用PROCA。假如,数据区1—3位为‘ABC’,&A中为ABCXY2,则测试结果为真,调用PROCA。
IF (((%SST*LDA 1 3) *CAT 'XYZ') *EQ &A) THEN(CALLPRC PROCA)
这个过程扫描变量&NUMBER且修改前导零或空格。这用在显示一个信息前加一个编辑字段:
DCL &NUMBER *CHAR LEN(5)
DCL &X *DEC LEN(3 0) VALUE(1)
.
.
LOOP:IF (%SST(&NUMBER &X 1) *EQ '0') DO
CHGVAR (%SST(&NUMBER &X 1)) ' ' /* Blank out */
CHGVAR &X (&X + 1) /* Increment */
IF (&X *NE 5) GOTO LOOP
ENDDO
下列过程使用%SST在50个字符的字段&INPUT中查找第一次出现的至少两个字符且没有嵌入句号的句子。然后把剩余内容放在&REMAINDER中。
PGM (&INPUT &REMAINDER) /* SEARCH */
DCL &INPUT *CHAR LEN(50)
DCL &REMAINDER *CHAR LEN(50)
DCL &X *DEC LEN(2 0) VALUE(03)
DCL &L *DEC LEN(2 0) /* REMAINING LENGTH */
SCAN: IF (%SST(&INPUT &X 1) *EQ '.') THEN(DO)
CHGVAR VAR(&L) VALUE(50-&X)
CHGVAR VAR(&X) VALUE(&X+1)
CHGVAR VAR(&REMAINDER) VALUE(%SST(&INPUT &X &L))
RETURN
ENDDO
IF (&X *EQ 49) THEN(RETURN)
CHGVAR &X (&X+1)
GOTO SCAN
ENDPGM
过程开始检查第三位是不是句号。从&INPUT的第三位开始长度为1的%SST,指的就是第三位(长度不能为零)。如果是句号,则计算剩余长度,&X中放的是余下部分的起始位置。余下部分的内容从&INPUT移到&REMAINDER中。
第三位不是句号,过程检查是否到了第49位。如果是,则假定第50位是句号且返回。如果不是,过程到&X从第4位开始重复这个处理。
2.5.9 使用%SWITCH内部函数
开关内部函数%SWITCH把8位中的1位或多位开关与已建立的8位作业开关相比较,返回一个逻辑值‘0’或‘1’。作业开关的初值由CRTJOBD命令确定,缺省值为8个零。如有需要,可用SBMJOB,CHGJOB或JOB命令中的SWS参数修改,这些缺省值是由作业描述设置的。其它高能语言也能设置作业开关。
如果%SWITCH的值与作业开头的值比较后,每位都相同,则返回‘1’。如果有一位
不匹配,则返回‘0’。
%SWITCH的语法为:
%SWITCH(8个屏蔽字符)。
8个屏蔽字符指出要测试哪个作业开关以及每个开关要测试的值。屏蔽位与作业开关的8个位相对应,每个屏蔽位能规定为0、1、X三个字符之一:
0:测试相对应的作业开关是否为0
1:测试相对应的作业开关是否为1
X:不测试相对应的作业开关,它不影响%SWITCH的结果。
例如,如果规定了%SWITCH(0X111XX0),那么测试作业开关1和8是否为0。作业
开关3、4、5是否为1,不测2、6、7位。如果作业开关的每位都与屏蔽位相同,则结果为1。
作业开关可用在CL过程中控制流程,可以与IF、CHGVAR命令一起使用。可用CHGJOB命令在CL过程中修改开关。对CL过程这些修改立即有效。
2.5.9.1 用%SWITCH的命令
在IF命令中,%SWITCH可在COND参数中规定做为要测试的逻辑表达式,在下例中,0X111XX0与作业开关相比较:
IF COND(%SWITCH(0X111XX0)) THEN(GOTO C)
如果作业开关的1、3、4、5、8依次是0、1、1、1和0,则结果为真,过程转移到标号为C处,如果作业开关有一位不符,则结果为假,不做转移操作。
在下面的例子中,开关控制二个过程的处理:
SBMJOB JOB(APP502) JOBD(PAYROLL) CMD(CALL APP502)
SWS(11000000)
PGM /* CONTROL */
IF (%SWITCH(11XXXXXX)) CALLPRC PROCA
IF (%SWITCH(10XXXXXX)) CALLPRC PROCB
IF (%SWITCH(01XXXXXX)) CALLPRC PROCC
IF (%SWITCH(00XXXXXX)) CALLPRC PROCD
ENDPGM
PGM /* PROCA */
CALLPRC TRANS
IF (%SWITCH(1XXXXXXX)) CALLPRC CUS520
ELSE CALLPRC CUS521
ENDPGM
2.5.9.2 用%SWITCH的CHGVAR命令
在CHGVAR命令中,可用%SWITCH来修改逻辑变量的值。逻辑变量的值是由%SWITCH与作业开关相比较确定的。如果结果为真,则变量值为‘1’,否则为‘0’,下例中,作业开关为10000001。&A的结果值为‘1’。
PGM
DCL &A *LGL
CHGVAR VAR(&A) VALUE(%SWITCH(10000001))
.
.
.
ENDPGM
2.5.10 使用监控信息命令MONMSG
逃逸信息是由CL过程中的命令或它们调用的程序或过程传送给CL过程的。信息告诉过程已检查到错误且没有完成功能。CL过程也能监控逃逸信息的到达,能用命令来处理这些信息。例如,如果一个CL过程试图往已删除的数据区移动数据,那么会由MOVOBJ命令发出‘目标没找到’的逃逸信息。
用MONMSG命令,要控制程序在有错误发生时立即采取什么样的动作,MONMSG可以监视逃逸、通知及状态信息,把它送到使用MONMSG命令的调用堆栈中。MONMSG有下列参数:
MONMSG MSGID(信息标识) CMPDTA(比较数据) EXEC(CL命令)
对每个错误发送的信息都有唯一的标识。在MSGID参数中最多可有50个标识,
CMPDTA参数用来检查在信息的MSGDTA部分的特别字符串,用EXEC参数规定做错误恢复的CL命令。(例如,CALL,DO或GOTO)
在下例中,MONMSG命令是跟在RCVF后,因此,它仅监控由RCVF发送的信息。
READLOOP: RCVF /* Read a file record */
MONMSG MSGID(CPF0864) EXEC(GOTO CMDLBL(EOF))
/* Process the file record */
GOTO CMDLBL(READLOOP) /* Get another record */
EOF: /* End of file processing */
在文件中没有可读记录时,CPF0864送到过程相关的队列中,由于规定了MSGID(CPF0864),MONMSG监控这个条件,当收到该信息后,运行GOTO命令。
也可用MONMSG命令来监控由CL过程中命令发送的信息。在下例中,有两个MONMSG命令,第一个监控信息CPF001和CPF1999。这些信息可能是过程中其后运行的任一命令发出的。不论收到哪个信息,控制都转移到由标号EXIT2标识的命令处。第二个MONMSG监控CPF2105和MCH1211。由于没有EXEC参数,则忽略此信息。
PGM
DCL
MONMSG MSGID(CPF0001 CPF1999) EXEC(GOTO EXIT2)
MONMSG MSGID(CPF2105 MCH1211)
.
.
.
ENDPGM
CPF0001标识信息本身指定的错误,大部分的调试命令发送CPF1999信息,它指出在命令中发现错误,但它不标识信息中的命令。
由MONMSG监控的错误条件都用EXEC参数规定的方式来处理,此例中是EXIT2,它也不可能返回出错后下一个顺序语句。要避免发生这种情况,可在每个命令之后监控条件,规定错误恢复例程。
所有没有规定EXEC的监控到的信息都被忽略,过程继续执行下个命令。
如果在计算IF命令的表达式时发生错误,条件做为假处理。在下例中,在IF中可能发生MCH1211错误,则条件为假,调用用PROCA。
IF(&A / &B *EQ 5) THEN(DLTF ABC)
ELSE CALLPRC PROCA
如果在CL过程的开始就用MONMSG命令,那么它监控整个过程中的规定信息,而不考虑是哪个命令产生的信息。如果用EXEC参数,那么只能规定GOTO命令。
在过程级或命令级可规定相同的信息标识,命令级的MONMSG要复盖过程级的。在下例中,如果在CMDB中收到信息CPF0001,则运行CMDC。如果在过程中的其它命令上收到CPF0001,过程转到EXIT2。如果在任何命令上接收到DCPF1999,转移到EXIT2。
PGM
MONMSG MSGID(CPF0001 CPF1999) EXEC(GOTO EXIT2)
CMDA
CMDB
MONMSG MSGID(CPF0001) EXEC(CMDC)
CMDD
EXIT2: ENDPGM
由于有很多逃逸信息会发送给过程,所以必须考虑你想监控处理哪一个。大多数信息在过程中有错时才发送,而另一些是由于条件超出过程外。一般来说,CL过程监控这些信息基本功能,且做适当的处理。对所有其它信息,&CPF假定发生了错误且采取了适当的缺省动作。处理信息的详细内容,请看第七章和第八章。
2.6 能做变量的值
2.6.1 取系统值
系统值包括控制操作系统某部分的信息。IBM提供了几类系统值,例如QDATE和QTIME是系统日期和时间,它是在&CPF起动时设置的。可用RTVSYSVAL命令在CL过程中把系统值做为变量来对待:
RTVSYSVAL SYSVAL(系统值名) RTNVAR(CL变量名)
RTNVAR参数规定接收系统值的过程中变量的名,变量的类型必须与系统值类型相匹配。对于字符和逻辑系统值,CL变量长度必须等于值的长度,对十进制变量的长度必须大于或等于系统值的长度。
2.6.1.1 系统值QTIME
在下例中,接收QTIME并把它放在一个变量中,然后与另外变量比较。
PGM
DCL VAR(&PWRDNTME) TYPE(*CHAR) LEN(6) VALUE('162500')
DCL VAR(&TIME) TYPE(*CHAR) LEN(6)
RTVSYSVAL SYSVAL(QTIME) RTNVAR(&TIME)
IF (&TIME *GT &PWRDNTME) THEN(DO)
SNDBRKMSG('Powering down in 5 minutes. Please sign off.')
PWRDWNSYS OPTION(*CNTRLD) DELAY(300) RESTART(*NO) +
IPLSRC(*PANEL)
ENDDO
ENDPGM
2.6.1.2 系统值QDATE
在很多应用中,都用当前的系统日期。这可用接收系统值QDATE把它放在一个变量中实现,也可能在应用过程中修改日期的格式,要转换格式,用CVTDTA命令。
系统日期的格式由系统值QDATFMT决定,初值为MDY(月日年)。可以把它改为YMD、DMY或JUL格式。JUL格式中,QDAY的值为001—366的三位字符,它用来确定两个日期之间的天数,可用CVTDAT命令来删除日期分隔符的字符,CVDDAT的格式为:
CVTDAT DATE(要转换的日期) TOVAR(CL变量) +
FROMFMT(旧格式) TOFMT(新格式) TOSEP(新分隔符)
DATE参数可以是常量或变量,日期一经转换好后,就放在TOVAR规定的变量中。在下例中,日期在&DATE中,它的格式为MDY,要转换为DMY格式放在变量&CVTDAT中:
CVTDAT DATE(&DATE) TOVAR(&CVTDAT) FROMFMT(*MDY) TOFMT(*DMY)
TOSEP(*SYSVAL)
日期分隔符使用系统值QDATSEP中规定的符号。
在生成或增加名字中有日期的目标或成员时,CVTDAT是很有用的。例如,假定成员要用当前的系统日期为名加到文件中,当前日期格式为MDY,要转换成JUL格式:
PGM
DCL &DATE6 *CHAR LEN(6)
DCL &DATE5 *CHAR LEN(5)
RTVSYSVAL QDATE RTNVAR(&DATE6)
CVTDAT DATE(&DATE6) TOVAR(&DATE5) TOFMT(*JUL) TOSEP(*NONE)
ADDPFM LIB1/FILEX MBR('MBR' *CAT &DATE5)
.
.
.
ENDPGM
假如当前日期为1988年1月5日,则增加的成员名为MBR88005。
在转换日期时,要注意以下几点:
在DATE参数中值的长度和TOVAR中变量的长度要与日期格式相匹配。TOVAR中变量长度至少是:
1. 对非JUL日期处理2位年:
a、在不用分隔符时,用6位字符。1978的7月28日写为072878。
b、在用分隔符时,用8位字符。1978年7月28日写为07-28-78。
2. 对4位年的非JUL日期:
a、不用分隔符时,用8位字符。1978年7月28日写为07281978。
b、在用分隔符时,用10位字符。1978年7月28日写为07-28-1978。
3. 对2位年的JUL日期:
a、不用分隔符时,用5位字符。1996年12月31日写为96365。
b、在用分隔符时,用6位字符。1996年12月31日写为96-365。
4. 对4位年的JUL日期:
a、不用分隔符时,要7位字符。1997年2月4日写为1997035。
b、用分隔符时,要8位字符。1997年2月4日写为1997-035。
如果转换的字符在变量中放不下,要有错误信息。如果比变量短,要在右边添空格。
除JUL格式外,年、月、日都是2字节字段,转换后的值都是右对齐,必要时添前导零。用JUL格式,日为3字节、年为2字节 ,转换后的值为右对齐,如需要,可加前导零。
下例是使用ILE连编API为转换成JUL格式的取当前本地时间。要生成程序,须用CRTBNDCL命令,或用CRTCLMOD,再用CRTPGM命令。
PGM
DCL &LILDATE *CHAR LEN(4)
DCL &PICTSTR *CHAR LEN(5) VALUE(YYDDD)
DCL &JULDATE *CHAR LEN(5)
DCL &SECONDS *CHAR 8 /* 从CEELOCT取得秒数 */
DCL &GREG *CHAR 23 /* 从CEELOCT取得阳历 */
/* */
CALLPRC PRC(CEELOCT) /* 取得当前日期和时间 */ +
PARMS (&LILDATE) /* Lilian 格式的日期 */ +
&SECONDS /* 不用的秒字段 */
&GREG /* 不用的阳历字段 */
*OMIT /* 省略反馈参数 */
CALLPRC PRC(CEEDATE) +
PARMS (&LILDATE) /* 今天的日期 */ +
&PICTSTR /* 如何格式化 */ +
&JULDATE /* 儒略日期 */ +
*OMIT
ADDPGM LIB1/FILEX MBR('MBR' *CAT &JULDATE')
ENDPGM
2.6.2 取配置源成员
用RTVCFGSRC命令,可把已有的配置目标用来建立CL命令源码,把源码放在一个源文件成员中。生成的CL源码可用于下列方面:
把配置在系统间交换
管理现场配置
备份配置(不用SAVSYS)
2.6.3 取配置状态
用RTVCFGSTS命令,可从三个配置目标中为应用程序取配置状态。三个配置目标为线路,控制器和设备。此命令用在CL过程中检查配置描述的状态。
2.6.4 取网络属性
用RTVNET命令可取得系统的网络属性。这些属性可用CHGNETA修改,用DSPNETA来显示。
下面是RTVNETA的例子:
PGM
DCL VAR(&OUTQNAME) TYPE(*CHAR) LEN(10)
DCL VAR(&OUTQLIB) TYPE(*CHAR) LEN(10)
RTVNETA OUTQ(&OUTQNAME) OUTQLIB(&OUTQLIB)
CHGNETA OUTQ(QGPL/QPRINT)
.
.
.
CHGNETA OUTQ(&OUTQLIB/&OUTQNAME)
ENDPGM
2.6.5 取作业属性
可取作业属性把它放在一个变量中来控制应用程序。所用的命令为RTVJOBA,可取得所有作业属性或它们的组合。
在下例中,RTVJOBA取得调用此过程的用户名字:
PGM
/* ORD410C Order entry program */
DCL &CLKNAM TYPE(*CHAR) LEN(10)
DCL &NXTPGM TYPE(*CHAR) LEN(3)
.
.
.
RTVJOBA USER(&CLKNAM)
BEGIN: CALL ORD410S2 PARM(&NXTPGM &CLKNAM)
/* Customer prompt */
IF (&NXTPGM *EQ 'END') THEN(RETURN)
.
.
变量&CLKNAM是传来的用户名,当调用ORD410S2时,要有两个变量&NXTPGM和&CLKNAM传给它,&NXTPGM传的是空格但可由ORD410S2来修改。
下例中,包括这个过程的程序由交互作业提交给批处理。用RTVJOBA命令取作业所用的信息队列名,用它来与提交作业的用户通信。
PGM
DCL &MSGQ *CHAR 10
DCL &MSGQLIB *CHAR 10
DCL &MSGKEY *CHAR 4
DCL &REPLY *CHAR 1
DCL &ACCTNO *CHAR 6
.
.
.
RTVJOBA SBMMSGQ(&MSGQ) SBMMSGQLIB(&MSGQLIB)
IF (&MSGQ *EQ '*NONE') THEN(DO)
CHGVAR &MSGQ 'QSYSOPR'
CHGVAR &MSGQLIB 'QSYS'
ENDDO
.
.
.
IF (. . . ) THEN(DO)
SNDMSG:SNDPGMMSG MSG('Account number ' *CAT &ACCTNO *CAT 'is +
not valid. Do you want to cancel the update +
(Y or N)?') TOMSGQ(&MSGQLIB/&MSGQ) MSGTYPE(*INQ) +
KEYVAR(&MSGKEY)
RCVMSG MSGQ(*PGMQ) MSGTYPE(*RPY) MSGKEY(&MSGKEY) +
MSG(&REPLY) WAIT(*MAX)
IF (&REPLY *EQ 'Y') THEN(RETURN)
ELSE IF (&REPLY *NE 'N') THEN(GOTO SNDMSG)
ENDDO
.
.
.
这里说明了两个变量,&MSGQ和&MSGQLIB,用来接收信息队列名及其库名。由于作业可能没规定信息队列名,那么把信息队列名与*NONE比较。如果相等,则表示没有信息队列,这时修改变量用QSYSOPR做信息队列名,用QSYS做库名。在检查到有错时,往信息队列送请求信息,并接收应答和处理。
在下列方面也可用RTVJOBA命令:
取得一个或多个作业属性,这样可做临时修改而后再改为原来的值。
取得一个或多个作业属性,用在SBMJOB命令中,这样使已提交和要提交的作业
属性相同。
2.6.6 取目标描述
可用RTVOBJD命令取某个目标的描述返回给CL过程,用变量来返回描述,也可用这些描述帮助你确定没有用的目标,也可用QUSRJOBD API来返回目标描述,也是用变量来返回的。
2.6.7 取用户配置文件属性
用RTVUSRPRF命令来取得用户配置文件的属性,把它们放在CL变量中来控制应用程序,可在命令中规定10个字符的用户配置文件名或用*CURRENT。在运行RTVUSRPRF后可监控逃逸信息。
在下面的CL过程中,用RTVUSRPRF取得调用CL过程的用户名和此用户的信息队列名:
DCL &USR *CHAR 10
DCL &USRMSGQ *CHAR 10
DCL &USRMSGQLIB *CHAR 10
.
.
.
RTVUSRPRF USRPRF(*CURRENT) RTNUSRPRF(&USR) +
MGSQ(&USRMSGQ) MSGQLIB(&USRMSGQLIB)
下列信息会返回给过程:
&USR中放的是调用这个程序的用户名
&USRMSGQ中放的是用户配置文件中规定的信息队列名
&USRMSGQLIB中放的是用户配置文件中规定的信息队列所在的库名
2.6.8 取成员描述信息
用RTVMBRD命令取数据库文件成员的信息,用在应用程序中。在下面的例子中,用RTVMBRD命令取规定成员的描述。假定数据库文件名为MFILE,放在MYLIB中,其中有三个成员(AMEMBER,BMBMBER和CMEMBER)。
DCL &LIB TYPE(*CHAR) LEN(10)
DCL &MBR TYPE(*CHAR) LEN(10)
DCL &SYS TYPE(*CHAR) LEN(4)
DCL &MTYPE TYPE(*CHAR) LEN(5)
DCL &CRTDATE TYPE(*CHAR) LEN(13)
DCL &CHGDATE TYPE(*CHAR) LEN(13)
DCL &TEXT TYPE(*CHAR) LEN(50)
DCL &NBRRCD TYPE(*DEC) LEN(10 0)
DCL &SIZE TYPE(*DEC) LEN(10 0)
DCL &USEDATE TYPE(*CHAR) LEN(13)
DCL &USECNT TYPE(*DEC) LEN(5 0)
DCL &RESET TYPE(*CHAR) LEN(13)
.
.
.
RTVMBRD FILE(*CURLIB/MYFILE) MBR(AMEMBER *NEXT) +RTNLIB(&LIB) RTNSYSTEM(&SYS) RTNMBR(&MBR) +
FILEATR(&MTYPE) CRTDATE(&CRTDATE) TEXT(&TEXT) +
NBRCURRCD(&NBRRCD) DTASPCSIZ(&SIZE) USEDATE(&USEDATE) +
USECOUNT(&USECNT) RESETDATE(&RESET)
能返回下列信息:
当前库名放到&LIB中
找到MYFILE的系统放到&SYS中(*LCL表示在本地系统找到文件,*RMT表示在远程系统中找到文件)
BMEMBER放到&MBR中,因为它在成员名列表中排在AMEMBER后面(*NEXT)
文件属性放到&MTYPE中(*DATA表数据成员,*SRC表源成员)
BMEMBER的生成日期放到&CRTDATE中
BMEMBER的说明放到&TEXT中
BMEMBER的当前记录数放到&MBRRCD中
BMEMBER的数据空间大小放到&SIZE中
BMEMBER最后中使用的日期放到&USEDATE中
BMEMBER已经使用的天数放到&USECNT中,它的起始日期放到&RESET中
有关使用RTVxxx命令的更多例子,可在QUSRTOOL中找到。
2.7 处理CL过程
一个CL源过程编译成模块,然后连编成程序才能运行,一步生成CL程序,可用CRTBNDCL命令与模块生成连编程序,也可用CRTCLMOD先生成模块,然后用CRTPGM或CRTSRVPGM命令连编成程序或服务程序。
下面例子用CRTCLMOD命令生成模块ORD040C并把它放到DSTPROLIB中。
CRTCLMOD MODULE(DSTPRODLB/ORD040C) SRCFILE(QCLSRC)
TEXT('Order dept general menu program')
ORD040C的源命令放在QCLSRC文件中,源成员名叫做ORD040C。在CRTBNDCL命令中,可以规定清单选项和是否在程序主人的用户配置文件下操作。一个程序可能在主人的用户配置文件下运行,也可在其它用户下运行。
可用PDM菜单中的选项或程序员菜单来生成CL过程和程序,这样可不用直接写CRTxxx命令。
2.7.1
在用CRTCLMOD或CRTBNDCL命令编译过程时,可在LOG参数中规定下列值之一来把过程中运行的大多数CL命令写到作业日志中。
*JOB,这是缺省值,它指出当规定作业日志选项为ON时要写日志,这个选项初
值为不做日志。但可用CHGJOB命令中的LOGCLPGM修改,这样,当
用*JOB值生成程序或模块时,能修改每个作业的日志选项。
*YES,规定只要运行CL过程就写日志,它不能用CHGJOB命令来修改。
*NO,规定不做日志,它不能用CHGJOB命令修改。
由于这些值是CRTCLMOD和CRTBNDCL命令的一部分,那么如修改它们必须重新编译。
在规定做日志时,要小心使用RMVMSG命令,不要从作业日志中移出任何日志命令。如果在RMVMSG命令中规定CLEAR(*ALL),那么所有在RMVMSG命令前运行命令的日志都从作业日志中清除掉,这个仅影响有RMVMSG的过程而不影响前后发生的已日志过的命令。
不是所有的命令都记到日志中,下面是不日志的命令:
CHGVAR DO GOTO
DCL ELSE IF
DCLF ENDDO MONMSG
PGM ENDPGM CALLPRC
如果日志选项为ON,则日志的信息送到过程的信息队列中。如果是交互地运行过程,而且作业的LOG参数中信息级别为4,则可用F10键来看所有命令的日志。如果在注销时规定*PRINT,则可打印日志。
日志包括时间、程序或过程名、信息正文和命令名。命令名是由源语句中限定的,也日志命令的参数。如果参数是变量,则打印变量的内容。
命令的日志会影响性能。
2.7.2 CL模块编译清单
在CRTCLMOD时,可用OPTION和OUTPUT参数来生成几类清单。
OPTION可用的值及意义为:
*GEN和*NOGEN,是否生成模块(*GEN为缺省值)
*XREF或*NOXREF,是否产生源输入的变量的交叉引用表或数据引用清单。
OUTPUT可用的值及意义为:
*PRINT——打印清单
*NONE——没有编译清单
规定了OUTPUT参数生成清单叫做编译清单,下面是清单的例子:
1
2
3
5763SS1 V3R1M0 940909 Control Language MYLIB/DUMPERR 05/06/94 11:12:55 Page 1
Program . . . . . . . . . . . . . . . . . . . : DUMPERR
Library . . . . . . . . . . . . . . . . . . : MYLIB
Source file . . . . . . . . . . . . . . . . . : QCLSRC
Library . . . . . . . . . . . . . . . . . . : MYLIB
Source member name . . . . . . . . . . . . . : DUMPERR 05/06/94 10:42:26 4
Source printing options . . . . . . . . . . . : *XREF *NOSECLVL *NOEVENTF
User profile . . . . . . . . . . . . . . . . : *USER
Program logging . . . . . . . . . . . . . . . : *JOB
Default activation group . . . . . . . . . . : *YES
Replace program . . . . . . . . . . . . . . . : *YES
Target release . . . . . . . . . . . . . . . : V3R1M0
Authority . . . . . . . . . . . . . . . . . . : *LIBCRTAUT
Sort sequence . . . . . . . . . . . . . . . . : *HEX
Language identifier . . . . . . . . . . . . . : *JOBRUN
Text . . . . . . . . . . . . . . . . . . . . : Test program
Optimization . . . . . . . . . . . . . . . . : *NONE
Debugging view . . . . . . . . . . . . . . . : *STMT
Compiler . . . . . . . . . . . . . . . . . . : IBM AS/400 Control Language Compiler 5
6 Control Language Source
SEQNBR *...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 ...+... 9 ...+. DATE 8
100- PGM 05/06/94
200- DCL &ABC *CHAR 10 VALUE('THIS') 05/06/94
300- DCL &XYZ *CHAR 10 VALUE('THAT') 7 05/06/94
400- DCL &MNO *CHAR 10 VALUE('OTHER') 05/06/94
500- CRTLIB LB(LARRY) 05/06/94
* CPD0043 30 Keyword LB not valid for this command. 9
600- DLTLIB LIB(MOE 05/06/94
* CPD0013 30 A matching parenthesis not found.
700- MONMSG CPF0000 EXEC(GOTO ERR) 05/06/94
800- ERROR: 05/06/94
900- CHGVAR &ABC 'ONE' 05/06/94
1000- CHGVAR &XYZ 'TWO' 05/06/94
1100- CHGVAR &MNO 'THREE' 05/06/94
1200- DMPCLPGM 05/06/94
1300- ENDPGM 05/06/94
* * * * * E N D O F S O U R C E * * * * *
5763SS1 V3R1M0 940909 Control Language MYLIB/DUMPERR 05/06/94 11:12:55 Page 2
Cross Reference
Declared Variables
Name Defined Type Length References
&ABC 200 *CHAR 10 900
&MNO 400 *CHAR 10 1100
10
&XYZ 300 *CHAR 10 1000
Defined Labels
Label Defined References 11
ERR ****** 700
* CPD0715 30 Label 'ERR ' does not exist.
ERROR 800
* * * * * E N D O F C R O S S R E F E R E N C E * * * * *
5763SS1 V3R1M0 940909 Control Language MYLIB/DUMPERR 05/06/94 11:12:55 Page 3
Message Summary
Severity
Total 0-9 10-19 20-29 30-39 40-49 50-59 60-69 70-79 80-89 90-99 12
3 0 0 0 3 0 0 0 0 0 0
Program DUMPERR not created in library MYLIB. Maximum error severity 30. 13
* * * * * E N D O F M E S S A G E S U M M A R Y * * * * *
下面是对图中标出号码处的解释:
标题:
1. 程序号码,版本,修改级别及&CPF的日期。
2. 编译的日期和时间。
3. 清单页号。
序:
4. 在CRTCLMOD中规定的参数值。如果源码不在数据库文件中,省去成员名,日期和时间。
5. 编译程序名称。
源码:
6. 源码中的行顺序号,顺序号后的‘一’指出源语句开始的顺序号,没有‘一’的语句是前面语句的继续。
源语句之间的注释与其它源语句一样处理且有顺序号。
7. 源语句。
8. 源语句修改或增加的最后日期,如果源语句不是在数据库文件中,则日期用RGZPFM重设且省略它。
9. 如果在编译期间发现有错,且能跟踪到某个语句,那么在这个语句之后立即打印错误信息。*指出这行有错,这行中给出信息标识、级别、和信息说明。详细内容请看2.7.3。
交叉引用:
10. 符号变量表是在程序中说明过的变量交叉引用列表。此表列出变量、说明变量的源语句顺序号,变量属性及引用此变量的语句顺序号。
11. 标号表是程序中定义的有效标号列表。此表列出标号,定义此标号的语句顺序号及引用此标号的语句顺序号。
信息:
此例中没有包括这段。这是因为它没有发出一般信息。如果有一般信息发出,这段对每个信息有一个给出信息标识、级别的说明。
信息总结:
12. 在编译期间,给出信息总结,以级别分类给出。
13. 在信息总结后给出完成信息。
标题、序号、源码和信息总结段的内容在有*SOURCE选项时都打印出来。如果
规定*XREF才打印交叉引用信息,如果有错误时才打印信息段内容。
用CL源成员中的CL命令编译程序编译它产生结果,需要一个中间系统码来完成程序运行时所需要的功能。
2.7.3 在编译期间遇到的错误
在模块的编译清单中,一个与命令有关的错误条件直接跟在此命令之后给出,不直接和某些命令有关的更一般的错误在信息段给出,它不放在源语句中间。
编译期间检查到的错误包括语法错误,引用一个没定义的变量或标号,语句错。下列错误会停止生成模块:
值错误
语法错误
命令中参数之间的关系错误
有效性检查错误
遇到以上各种错误,编译程序继续检查源语句。程序员可以看编译清单改正多处错误,再次编译生成模块。
2.7.4 获得过程转储
在处理过程期间可得到转储结果。转储由过程信息队列的所有信息以及所有变量说明组成,可用它来解决影响过程执行出现的问题。要得到转储,做下列之一:
运行DMPCLPGM命令,这个命令仅用在CL过程中,不能结束过程。
对CPA0702信息回答D,这个信息是在有没监控的逃逸信息时发出的。如果程序
在交互下运行,信息送往作业的外部信息队列。如果程序是做为批作业运行,信息送往操作员信息队列。
对作业规定INQMSGRPG(*SYSRPYL),它要求回答信息CPA0702或CPA0701。
在送出回答后会打印转储。
把对信息CPA0702信息回答的缺省值C改为D,当发生功能检查时会打印过程
转储,要改缺省值,用下列命令:
CHGMSGD MSGID(CPA0702) MSGF(QCPFMSG) DFT(D)
注:此命令是有权限限制的。
在下列条件之一下修改信息缺省值能打印转储:
系统操作员信息队列是在缺省方式且信息是从批作业发出的,工作站用户没给出
回答按执行键,则用信息缺省值。
对作业规定INQMSGRPY(*DFT)。
1
5763SS1 V3R1M0 940909 CL Program Dump 5/24/94 11:05:03 2 Page 1
Job name . . . . . . . . : DSP04 3 User name . . . . . . : SMITH 3 Job number . . . . . . : 01329 3
Program name . . . . . . : DUMP 4 Library . . . . . . . : MYLIB 4 Statement . . . . . . . : 1200 5
Module name . . . . . . : DUMP Procedure name . . . : DUMP
Messages
Message 6 Message From To
Time ID Sev Type Text Program Inst Program Inst
110503 CPC2102 00 COMP Library LARRY created. QLICRLIB *N DUMP *N
110503 CPF2110 40 ESC Library MOE not found. QLICLLIB *N DUMP *N
Variables 7
Variable Type Length Value Value in Hexadecimal
*...+....1....+....2....+ * . . . + . . . . 1 . . . . + . . . . 2 . . . . +
&ABC *CHAR 10 'ONE ' D6D5C540404040404040
&XYZ *CHAR 10 'TWO ' E3E6D640404040404040
* * * * * E N D O F D U M P * * * * *
1. 程序号,版本修改级别和&CPF日期。
2. 打印转储的日期和时间。
3. 过程运行的作业全名。
4. 程序名及库名。
5. 产生转储时的语句号。如果命令是嵌套的,语句号是外部命令的语句号。
6. 调用信息队列的每个信息。包括信息发送的时间、信息标识、级别、类型、说明、发送的程序和指令号码,以及接收的程序和指令号码。
7. 程序中说明的所有变量。包括变量名、类型、长度、值和十六进制值。如果十进变量中有无效十进数,则做为*CHAR变量打印字符或十六进制值。
如果没分配变量的值,则打印*NOT ADDRESSABLE。如果程序中有TYPE(*NULL)或PASSVAL(*NULL)参数的命令时,或规定了RTNVAL(*YES),但没给出返回的变量,则会发生这种情况。
如果变量是TYPE(*LGL),在转储中它做为1位长的*CHAR给出。
2.7.5 显示模块属性
用DSPMOD可显示模块属性,这个信息可用来确定生成模块所用命令的选项。
2.7.6 显示程序属性
可用DSPPGM命令来显示一个程序的属性,它可用来确定生成程序所用命令的选项。
2.7.7 返回码总结
在RTVJOBA命令中的 RTNCDE参数是五位无小数的十进制值,它指出被调用程序的状态。
下表给出&SYS支持的语言所用返回码:
RPG IV程序:
由RPG IV编译程序发出的返回码是:
0 程序生成了
1 程序没生成
由运行RPG IV程序发出的返回码是:
0 程序起动或由CALL调用程序
1 程序以LR为ON结束
2 程序因错误结束
3 程序因指示器失败结束
在CALL后检查出的RPG IV返回码:
0或1 无错
3 给出RPG IV状态码231
其它值 给出RPG IV状态码202(CALL因错误结束)
返回码不能相接用用户测试。
CL程序:
返回码的当前值可用RTVJOBA中的参数RTNCDE得到。
2.8 编译以前版本的源程序
可用CRTCLPGM中的TGTRLS参数来编译以前版本写的源程序。TGTRLS规定试图运行在哪个版本下生成的CL目标程序,可以规定*CURRENT,*PRV或某一个版本号。
用TGTRLS(*CURRENT)编译的程序仅能在当前版本或以后版本运行,用其它的值编译的程序能在规定版本及以后版本下运行。
2.8.1 以前版本(*PRV)库
CL编译程序从CL以前版本库中取得以前版本的命令和文件信息。有二类库包含这种支持:系统库和用户库。各字分别为QSYSVxRxMx 和QUSRVxRxMx。例如,QUSRV2R2M0就表示是支持版本2.20系统。
在CL编译程序编译支持以前版本的程序时,首先要检查在以前版本库中的命令和文件,如果查找失败,则查找库列表和以下的限定库:
QSYSVxRxMx库:当CL编译程序支持以前版本时就安装了这些库,库中包括在
QSYS库中找到的为某个版本的目标定义的命令和输出文件。
QUSRVxRxMx库:可以自己生成这个库来放支持以前版本的命令和文件的复本。
如果在当前版本下修改了命令或文件,这是特别重要的。
当编译程序查找以前版本命令和文件时,先查QUSRVxRxMx,再查QSYSVxRxMx。
注:用QUSRVxRxMx来放以前版本的命令和文件,可不用QSYSVxRxMx。在安装以
后版本的CL编译程序时,也安装支持后来版本的CL编译程序,用时也安装支持以前版本的,可以修改或取消QSYSVxRxMx库。
不要把以前版本的库加到库列表中,它们包括不能在当前系统下运行的命令或文件。仅仅CL编译程序可以使用和引用以前版本库中的命令和文件,支持以前版本的系统命令是在系统的主语言中,没有第二语言可用。
对如何保存不同版本下的目标,请看相应的CL参考手册。
2.8.1 安装支持以前版本的CL编译程序
要安装*PRV CL编译程序和QSYSVxRxMx库:
1. 在命令行上输入GO LICPGM,出现特许程序菜单。
2. 选11。
3. 选择5769SS1—*PRV CL COMPILER SUPPORT。它安装QSYSVxRxMx库。
如果不用这个库,可用下列命令去掉:
DLTLICPGM LICPGM(5769SS1) OPTION(9)
移出后,QSYSVxRxMx不在系统中了,但QUSRVxRxMx还在,如果也不用它,要用DLTLIB命令删除它。