内容


IBM i 平台上 CL 命令的开发

IBM i 平台上与 CL 命令相关的知识介绍和程序设计

Comments

IBM i 平台上 CL 命令的开发

CL 命令介绍

CL 命令是 IBM i 绿屏界面上的重要交互方式。程序员、信息处理员和系统管理员都可以直接使用 CL 命令来进行开发和日常系统管理。CL 是 control language 的缩写,它是 IBM i 上的主要接口,它可以在同一时间被不同用户在不同的工作站上使用。它虽然只有一条语句, 但是通过 IBM i 命令菜单、强大的命令提示工具和在线命令帮助,即使是非技术人员也能够使用 CL 命令。

IBM i 平台上提供了大量的 CL 命令给用户使用,同时也允许用户自己开发集成新的 CL 命令,去完成自定义的任务,而如何开发一条 CL 命令是本文说要讲述的主要内容。

定义 CL 命令

通常一个 CL 命令是由三个部分组成的,命令的名字、关键字和值,如图 1 所示。在本文中,将会通过创建一个简单的 CL 命令来描述一个自定义编写 CL 命令的过程。下面,我们通过一个简单的例子来看一下如何创建一个自定义的 CL 命令。

图 1. CL 命令组成部分
图 1. CL 命令组成部分
图 1. CL 命令组成部分

这个 CL 命令是 DLTEXPOBJ,它有 PATH, DAYS 这 2 个参数,用来删除 PATH 路径下面最近 DAYS 天没有访问的文件。它的使用方法是 DLTEXPOBJ PATH('/HOME/YANLINBJ') DAYS(21),图 2 显示了编写一个 CL 命令所需要的几个步骤。

图 2. 编写 CL 命令的几个步骤
图 2. 编写 CL 命令的几个步骤
图 2. 编写 CL 命令的几个步骤
  1. 定义 CL 命令的源文件,你可以编写一个 CL 命令的源文件来定义一个 CL 命令。
  2. 用 CRTCMD 命令来编译你的 CL 命令源文件。
  3. 编写命令执行程序 command processing program (CPP),CPP 是被 CL 命令调用来实现功能的程序。可以是 CL 程序,也可以是其他一些高级语言程序,比如 C/C++,COBOL。CL 命令的参数定义语句将参数传给 CPP,CPP 接受的参数会根据参数的类型,而有所不同。
  4. 有效性检测程序 (Validity CheckingProgram)、提示控制程序 (Prompt Control Program) 和提示重载程序 (Prompt Override Program) 这些程序是可选的,一个可执行的 CL 命令可以不包括这些程序,具体请参考本文 EXIT P PROGRAM/EXIT POINT 部分。

CL 命令源文件

在一个 CL 命令的源文件里,只能输入一个 Command(CMD) 语句,CMD 语句定义了这个命令的名字。大多数的 CL 命令都有一个或者多个参数,比如 DLTEXPOBJ 这个 CL 命令就有 PATH 和 DAYS 两个参数。每个存在的参数都必须定义一个 Parameter(PARM),也可以利用的 ELEM 语句和 QUAL 语句来定义一些更复杂的参数,比如列表的参数(ELEM),限定符(QUAL)。如果需要检测一些指定参数之间的关系,可以通过使用依赖 (DEP) 语句。DEP 只能用于那些已经定义的参数。提示控制(PMTCTL)语句可以用来有选择的显示那些命令参数。

需要注意的是,一个源文件只能定义一个 CL 命令。PARM 参数的顺寻决定了这个参数在 CL 命令中的顺序。编译 CL 命令的时候,你可以采用 Create Command(CRTCMD) 命令,根据一个源文件中的命令定义语句来创建一个命令定义对象。

命令定义对象(Command define object) 是所有与这个命令有关的对象集合。包括有效性检测,CPP,和提示重载程序。

清单 1. DLTEXPOBJ 命令的定义示例 1
 CMD     PROMPT('Delete EXPIRED ') 
 PARM    KWD(PATH) TYPE(*PNAME) LEN(256) VARY(*YES *INT4) + 
 MIN(1) MAX(1) CASE(*MIXED) PROMPT('Path') 
 PARM    KWD(DAYS) TYPE(*INT4) DFT(1) MIN(0) MAX(1) + 
 RANGE(0 255) PROMPT(' Non-accessed')

在 DLTEXPOBJ 的 PATH 参数中,TYPE(*PNAME) 说明参数 PATH 的类型是 *PNAME, LEN(256) 设定参数的长度是 256,MIN(1) MAX(1) 说明 PATH 这个参数必须也只能有一个值输入,CASE(*MIXED) 说明输入的字符串大小写无关,PROMPT('Path') 说明 PATH 参数的提示是“Path”。通常,为了考虑到不同语言之间的差异,参数中的文本通常可以使用消息 ID 来标识。在这个例子中,PROMPT('Path') 中的'Path' 这个文本可以用一个消息 ID(比如 USR0001) 来代替。这样,对于不同的语言,当 CL 命令需要移植的时候,它就不需要对代码进行修改,只需要翻译消息 (USR0001) 即可。

需要指出的是,PATH 传给 CPP 的是一个 256 字节长的字符串。如果输入的字节不满 256,用' '空格来填充。

图 3. 参数 PATH 的结构
图 3. 参数 PATH 的结构
图 3. 参数 PATH 的结构

VARY(*YES *INT4) 是用一个 4 个字节长的整型数来标记 PATH 参数的实际长度。指定 VARY(*YES *INT4) 之后,传给 CPP 的参数 PATH 就由 2 个部分组成(如图 3 所示)。第一部分是一个 4 字节长的整形数,这个值等于 PATH 字符串的长度。第二部分是一个长度为 256 字节的字符串,如果输入的字节长度不满 256,余下字节会被用空格来填充。

关于更多的 CL 命令参数的说明可以参考 IBM i Information Center 中 CL 命令参数的相关部分: http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/topic/rbam6/prtyp.htm

接下来我们就可以给予上述的源文件使用 清单 2 的命令来创建一个可以被执行的 *CMD 对象了。其中 PGM 参数就是指 CL 命令的 CPP 程序,SRCFILE 是 CL 命令的定义语句的源文件。

清单 2. 创建 CL 命令
 CRTCMD CMD(DLTEXPOBJ) PGM(QGPL/QDLTEXPOBJ) SRCFILE(QGPL/QCMDSRC)

命令执行程序 command processing program (CPP)

本节我们将会描述如何编写一个 CPP 程序。在 CPP 程序中,我们创建一个结构用来存储接收到的命令参数。这样有几个好处,

  1. 容易处理 CL 命令传来的参数。
  2. 易于使用。在随后的程序中,只需要对这个结构对象进行操作即可。
清单 3. 命令执行程序示例
 typedef _Packed struct instParms1 { 
 int pathLen; // *INT4, specific the length of path 
 char path[256]; // *CHAR, path characters array 
 int days; // *INT4 
 } inputParms; 
 ...... 
 int main (int argc, char *argv[]) 
 { 
 char path[256] = {0}; 
 int days = 0; 
 /**********************************************************/ 
 /* Initialize the input data from the CPP */ 
 /**********************************************************/ 
 inputParms * input = (inputParms *) argv[1]; 
 memcpy (path, inputParms->path, input->pathLen); //Copy the path string 
 days = input->days; 
 /**********************************************************/ 
 /*Begin the delete operation */ 
 /**********************************************************/ 
 ...... 
 }

pathLen 对应于 PATH 参数的第一部分,指明了传进来的 PATH 字符串的有效长度。path[256] 是用来存放 PATH 字符串的数组,days 是 CPP 收到的 DAYS 参数。在接下来的程序中,会根据接收的参数,对与 PATH 路径下 days 天没有访问的文件进行删除,这部分的代码就不在本文中显示。

EXIT PROGRAM/EXIT POINT

EXIT PROGRAM 叫做出口函数,这是一个类似于回调函数的一类程序。当用户将某个程序指定为 EXIT PROGRAM 时,这个 EXIT PROGRAM 就可以在特定的事件或条件下被另外的一方调用。EXIT POINT 相当于函数指针,当用户将某个程序注册到这个 EXIT POINT 之后,这个程序就可以在特定的时间或条件下被另外的一方调用。在一个 EXIT POINT 上可以注册多个 EXIT PROGRAM。 在 CL 命令中,上文提到的 CPP,VCP,POP,CHOICE PGM, PCP 这些都是 EXIT PROGRAM。除了 CPP 是必须存在的以外,其他的 EXIT PROGRAM 和 EXIT POINT 都是可选的,用户可以根据实际需求来决定是否使用它们。

有效性检测程序 (Validity Checking Program)

如果系统提供的有效性检测无法满足用户的需求,可以通过自定义编写有效性检测程序来替代系统的有效性分析。我们继续上文的 DLTEXPOBJ 这个命令。现在有个新的需求,用户希望只能删除 /home 目录下面的文件。系统的检测只能就字符长度,是否为合法字符这些基本规则做一个检测,他并没有办法检测我们这种针对性很强的需求。

此时,用户可以通过编写有效性检测程序来检测参数的正确性。用户可以在 CRTCMD 的时候通过参数 VLDCKR 来指定 VCP 程序,也可以通过 CHGCMD 命令在 CMD 定义里面指定 VLDCKR。

清单 4. 定义有效性检测程序的命令
 CRTCMD CMD(SAMPLECMD) PGM(QGPL/QSAMPLECMD) 
 SRCFILE(QGPL/QCMDSRC) 
 VLDCKR(QGPL/PATHVCP)

同时,用户也可以在命令定义源文件里面加上 VLDCKR 这个参数,那么在 CRTCMD 的时候 QGPL/PATHVCP 就会被设置为 VCP。

清单 5. 在 CL 命令源文件中定义有效性检测程序
 CMD    PROMPT('Delete EXPIRED ') VLDCKR(QGPL/PATHVCP) 
 PARM   KWD(PATH) TYPE(*PNAME) LEN(256) VARY(*YES *INT4) + 
 MIN(1) MAX(1) CASE(*MIXED) PROMPT('Path') 
 PARM   KWD(DAYS) TYPE(*INT4) DFT(1) MIN(0) MAX(1) + 
 RANGE(0 255) PROMPT(' Non-accessed')

具体可以参考 IBM i Information Center 中 Validity Checking Program 的相关部分:http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=%2Frbam6%2Fwvchk.htm

提示重载程序 Prompt Override Program(POP)

提示重载程序(Prompt Override Program) 可以提供参数的当前值作为参数的默认值。比如我们输入 CHGJOB,有些值是 *SAME,有些值是该参数的当前值。POP 程序就是按照特定的格式,将参数的当前值传给 CL 命令,CL 命令再将其显示出来。

用户可以在 CRTCMD 的时候通过参数 PMTOVRPGM 来指定 POP 程序,也可以通过 CHGCMD 命令在 CMD 定义里面指定 PMTOVRPGM。

清单 6. 定义提示重载程序的命令
 CRTCMD CMD(SAMPLECMD) PGM(QGPL/QSAMPLECMD) 
 SRCFILE(QGPL/QCMDSRC) 
 VLDCKR(QGPL/PATHVCP) 
 PMTOVRPGM (QGPL/PATHPOP)

同时,用户也可以在命令定义源文件里面加上 PMTOVRPGM 这个参数,那么在 CRTCMD 的时候 QGPL/PATHVCP 就会被设置为 VCP。

清单 7. 在 CL 命令源文件中定义提示重载程序
 CMD     PROMPT('Delete EXPIRED ')  + 
 VLDCKR(QGPL/PATHVCP) + 
 PMTOVRPGM (QGPL/ PATHPOP) 
 PARM    KWD(PATH) TYPE(*PNAME) LEN(256) VARY(*YES *INT4) + 
 MIN(1) MAX(1) CASE(*MIXED) PROMPT('Path') 
 PARM    KWD(DAYS) TYPE(*INT4) DFT(1) MIN(0) MAX(1) + 
 RANGE(0 255) PROMPT(' Non-accessed')

具体可以参考 IBM i Information Center 的 Prompt Override Programs 的相关部分:http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=%2Frbam6%2Fpop.htm

选项程序(Choice Program)

现在用户又有另一个需求,他希望对于 PATH 这个参数,当按下 F4 的时候能够显示现在 /home/ 路径下所有的文件夹。

CHOICE PGM 可以为某些参数提供一些可能的参考值。比如,对于 DSPPTF 这个命令,“Product”这个参数,我们按 F4 的时候,会弹出目前 Product 的所有可能值,这些值就是由 CHOICE PGM 来提供的。CHOICE PGM 可以通过 CL 命令定义源文件里面的 PARM or ELEM or QUAL 语句中指定 CHOICE PGM 这个参数来指定 CHOICE PGM。对于如何编写一个 CHOICE PGM,大家可以参考 IBM i Information Center 上的选项程序(CHOICE PROGRAM)相关部分:http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/topic/rbam6/pmtpc.htm

提示控制程序 (Prompt Control Program)

在上文提到过,PMTCTL 可以让 CL 命令在不同的条件情况下只显示那些需要显示的参数。提示控制程序(PCP)通过对某个参数进行处理,按照特定格式,将一个返回值传给 PMTCTL 语句。

比如在 DLTEXPOBJ 这个命令中,用户新添加了一个需求,希望添加一个参数 NAME。PCP 会根据参数 NAME 的输入值,来判断输入的是库(LIBRARY)的名字还是一个路径名。然后 PMTCTL 会根据 PCP 返回的值,只显示需要显示的参数。如果用户输入的是一个库的名字,那么 CL 命令就只会显示与库相关的参数。如果输入的是一个路径名,就只会显示那些与路径相关的参数。

具体可以参考 IBM i Information Center 上的提示控制程序 (Prompt Control Program) 相关部分:

http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/topic/rbam6/condp.htm

QIBM_QCA_CHG_COMMAND

QIBM_QCA_CHG_COMMAND 这个 exit point 可以为一个已经存在的命令注册一个新的完全不同的命令,这点来说有点类似于 UNIX 的 alias。这个新的命令不但可以名字有所不同,甚至可以是另一个 library 里面完全不同的命令。与别名 (alias) 相比,他还能够替换一个命令里面的部分参数,从这点来说 QIBM_QCA_CHG_COMMAN 使得 CL 命令更加灵活。需要注意的是,QIBM_QCA_CHG_COMMAND 能够并且也只能够为一个命令注册 exit point。

清单 8 显示了如何为 MYLIB/DLTEXPOBJ 注册一个 QIBM_QCA_CHG_COMMAND exit point。

清单 8. 注册 QIBM_QCA_CHG_COMMAND 命令
 ADDEXITPGM EXITPNT(QIBM_QCA_CHG_COMMAND) 
           FORMAT(CHGC0100)             
           PGMNBR(1)                   
           PGM(MYLIB/CHGEXIT)  
           TEXT('Exit program for DLTEXPOBJ') 
           PGMDTA(*JOB 20 'DLTEXPOBJ MYLIB')

更多信息,大家可以参考 IBM i Information Center 上的相关部分:http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/topic/apis/xcachg.htm

QIBM_QCA_RTV_COMMAND

QIBM_QCA_RTV_COMMAND 是 CL 命令的另一个 exit point。它是在命令分析器执行之后,CPP 程序执行之前被调用的。比如可以有一个新的需求,需要把每一次执行 DLTEXPOBJ 这个命令之后,在 QHST 里面记录这个命令的执行情况。用户需要开发一个程序(PGM),用来向 QHST 里面记录命令的执行情况,然后再把这个 PGM 注册到 QIBM_QCA_RTV_COMMAND 上。

清单 9 显示了如何为 MYLIB/DLTEXPOBJ 注册一个 QIBM_QCA_RTV_COMMAND exit point。

清单 9. 注册 QIBM_QCA_RTV_COMMAND 命令
 ADDEXITPGM EXITPNT(QIBM_QCA_RTV_COMMAND) 
           FORMAT(RTVC0100)             
           PGMNBR(1)                   
           PGM(MYLIB/RTVEXIT)  
           TEXT('Exit program for DLTEXPOBJ') 
           PGMDTA(*JOB 20 'DLTEXPOBJ MYLIB')

更多信息,大家可以参考 IBM i Information Center 上的相关部分:http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/topic/apis/xcartv.htm

总结

本文介绍了 CL 命令的基本概念和 CL 命令开发中比较高级的应用:EXIT PROGRAM 和 EXIT POINT。通过实际例程演示了如何开发一个简单的 CL 命令,希望能给 CL 命令的开发者提供一些参考。更多关于 CL 命令的开发资料可以参见参考资料。


相关主题

  • 参考 IBM i 信息中心,获取更多关于 IBM i CL 命令的信息。
  • 参考 Wiki 百科上关于 CL 命令的更多信息。
  • IBM developerWorks 中国 IBM i 专区:为 IBM i 的开发人员准备的技术信息和资料。这里提供产品下载、how-to 信息、支持资源以及免费技术库,包含 2000 多份技术文章、教程、最佳实践、IBM Redbook 和在线产品手册。

评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=IBM i
ArticleID=815519
ArticleTitle=IBM i 平台上 CL 命令的开发
publish-date=05142012