CL命令如何构建精确的参数列表?

时间:2017-08-02 21:47:52

标签: ibm-midrange rpgle control-language

我有一个驱动RPGLE程序的CMD命令对象。因为可以使用几个不同的参数调用命令,其中一些参数是互斥的,所以我使用RPGLE中的数据结构解析传递的参数,这样我就可以处理在不同位置传递参数的不同场景。

例如,CMD文件具有:

CMD       PROMPT('Reprint Invoices and Credits')      

 PARM      KWD(ORDERNUM) TYPE(ORDER) +                 
           PROMPT('For order number:')                 

 PARM      KWD(INVDATE) TYPE(*DATE) PASSATR(*YES) +    
           PROMPT('For invoice date')                  

 PARM      KWD(DATERANGE) TYPE(DTRANGE) +              
           PROMPT('For date range:')      

 PARM      KWD(TRANSTYPE) TYPE(*CHAR) LEN(9) RSTD(*YES)      +
              DFT(*BOTH) VALUES(*INVOICES *CREDITS *BOTH)    +
              PASSATR(*YES) PROMPT('Transactions to print')   

 DTRANGE:  ELEM      TYPE(*DATE) MIN(1) PASSATR(*YES) +             
                     PROMPT('Beginning date')                       
           ELEM      TYPE(*DATE) MIN(1) PASSATR(*YES) +             
                     PROMPT('Ending date')                          

 ORDER:    ELEM      TYPE(*DEC) LEN(6) MIN(1) PASSATR(*YES) +       
                     PROMPT('Order number')                         
           ELEM      TYPE(*DEC) LEN(2) MIN(0) PASSATR(*YES) +       
                     PROMPT('Shipment number (optional)')           

           DEP       CTL(*ALWAYS) PARM(ORDERNUM INVDATE DATERANGE) +
                     NBRTRUE(*EQ 1)                                 

用户可以按各种标准打印:订单号,日期,日期范围。只能选择这三种方法中的一种。根据用户选择的内容,参数以不同方式传递给被调用的RPGLE程序。

  ********************************************************************                           
  *      Parameters from CMD object INV_REPRNT                                                   

 D InputParms      DS                  TEMPLATE QUALIFIED                                        
 D  AllParms                    143A                                                             
 D  ParmType               2      2A                                        Can't find in manual 
 D                                                                          'Type' might be      
 D                                                                          a misnomer           
 D                                                                                               
 D  OrdDteAttr             3      3A                                        For attr's, see      
 D  OrderNum               4      7P 0                                      SEU help for         
 D  ShipAttr               8      8A                                        CMD PASSATR          
 D  Shipment               9     10P 0                                                           
 D  OrdInvCMAttr          21     21A                                                       
 D  OrdInvCM              22     30A                                        char  9        
 D                                                                                 
 D  InvDate@               4     10A                                               
 D  DteInvCMAttr          13     13A                                               
 D  DteInvCM              14     22A                                        char  9
 D                                                                                 
 D  BeginDateAttr         13     13A                                               
 D  BeginDate@            14     20A                                               
 D  EndDateAttr           21     21A                                               
 D  EndDate@              22     28A                                               
 D  RgeInvCMAttr          29     29A                                               
 D  RgeInvCM              30     38A                                        char  9

如您所见,后面的参数如TRANSTYPE的位置根据选择的早期参数移位。 OrdInvCM从22开始,DteInvCM从14开始,RgeInvCM从30开始。这不是问题,因为此数据结构和使用它的代码能够选择正确的位置根据我调用ParmType的神秘小属性读取。据我所知,这个属性没有在互联网上的CL手册或SEU编辑器中包含的帮助中的任何地方记录(其中PASSATR的信息不在在线手册中)。我已经将与ParmType相关的一些PASSATR行为拼凑起来,足以使用它,但还不足以完全理解它。

使解析 D Null C CONST(X'00') D Parm2 C CONST(X'02') D NumSpecd C CONST(X'A1') 1010 0001 D NumUnspecd C CONST(X'21') 0010 0001 D CharQSpecd C CONST(X'C5') 1100 0101 Quoted D CharQUnspecd C CONST(X'45') 0100 0101 Quoted D CharUQSpecd C CONST(X'85') 1000 0101 Unquoted D CharUQUnspecd C CONST(X'05') 0000 0101 Unquoted D D IsSpecd C CONST(X'80') >= 1000 0000 更容易(不是每种可能性)的一些常量:

 IF P.ParmType = Null;         
   IF P.OrdDteAttr >= IsSpecd; 
     // this is a single date
   ELSE;
     IF P.BeginDateAttr >= IsSpecd;
       // this is a data range
     ELSE;
       // this is error condition I have not gotten yet
     ENDIF;
   ENDIF;
 ELSE;
   IF P.OrdDteAttr >= IsSpecd;
     // this is an order number
   ELSE;
     // this is error condition I have not gotten yet
   ENDIF;
 ENDIF;

我发现:

ParmType

换句话说,ParmType的十六进制值为' 00'当参数是日期或日期范围时。 ParmType的十六进制值为' 02'当参数为'订单号'的打包* DEC(6P 0)时。

我想了解如何将[{"name":"Fressnapf","isChecked":true},{"name":"Whiskas","isChecked":true},{"name":"Purina","isChecked":true}] 值设置为给定数字,以便我可以强大地编写可以接受各种参数组合的程序。我也没有看到为什么数据范围字段从14开始而不是像单个日期那样在4开始的特定原因。我能够利用这个事实来做出必要的区分,但我不知道命令系统是否有意 ,因为它看到我有两种相同数据类型的可能性,或者这是只是一个幸运的休息,不能保证会发生。如果我想添加一个额外的打包参数作为选项,比如发票号,则会出现类似的问题。 ' PASSATR' ' A1'的十六进制值可以告诉你包装,但不是哪种类型(订单号或发票号)。可能是命令系统将位置移动到类似于日期范围的位置,但我没有运行该特定实验。

简而言之,是否有关于命令如何构建参数列表的文档或至少推导出的算法,以便人们可以预测这些字段将包含哪些内容以及它们将位于何处?

3 个答案:

答案 0 :(得分:4)

无论是否输入值,都将传递所有参数,它们将按照命令中提供的顺序显示。

不应该需要

PASSATR,请不要这样做。

CMD       PROMPT('Reprint Invoices and Credits')

  PARM      KWD(ORDERNUM) TYPE(ORDER) +
            PROMPT('For order number:')

  PARM      KWD(INVDATE) TYPE(*DATE) +
            PROMPT('For invoice date')

  PARM      KWD(DATERANGE) TYPE(DTRANGE) +
            PROMPT('For date range:')

  PARM      KWD(TRANSTYPE) TYPE(*CHAR) LEN(9) RSTD(*YES) +
            DFT(*BOTH) VALUES(*INVOICES *CREDITS *BOTH)  +
            PROMPT('Transactions to print')

  DTRANGE:  ELEM      TYPE(*DATE) MIN(1) +
                      PROMPT('Beginning date')
            ELEM      TYPE(*DATE) MIN(1) +
                      PROMPT('Ending date')

  ORDER:    ELEM      TYPE(*DEC) LEN(6) MIN(1) +
                      PROMPT('Order number')
            ELEM      TYPE(*DEC) LEN(2) MIN(0) +
                      PROMPT('Shipment number (optional)')

            DEP       CTL(*ALWAYS) PARM(ORDERNUM INVDATE DATERANGE) +
                      NBRTRUE(*EQ 1)

混合列表ORDERNUMDATERANGE将以整数个元素作为前两个字节出现。如果混合列表参数为空或未传递,则此整数将包含0。

以下是如何在CL

中编写命令处理程序的代码
PGM        PARM(&ORDERNUM &INVDATE &DATERANGE &TRANSTYPE)

         DCL        VAR(&ORDERNUM) TYPE(*CHAR)
         DCL        VAR(&ONELMCNT) TYPE(*INT) STG(*DEFINED) +
                      LEN(2) DEFVAR(&ORDERNUM 1)
         DCL        VAR(&ONORDER) TYPE(*DEC) STG(*DEFINED) LEN(6 +
                      0) DEFVAR(&ORDERNUM 3)
         DCL        VAR(&ONSHIPNO) TYPE(*DEC) STG(*DEFINED) +
                      LEN(2 0) DEFVAR(&ORDERNUM 7)

         DCL        VAR(&INVDATE) TYPE(*CHAR) LEN(7)

         DCL        VAR(&DATERANGE) TYPE(*CHAR)
         DCL        VAR(&DRELMCNT) TYPE(*INT) STG(*DEFINED) +
                      LEN(2) DEFVAR(&DATERANGE 1)
         DCL        VAR(&DRBDATE) TYPE(*CHAR) STG(*DEFINED) +
                      LEN(7) DEFVAR(&DATERANGE 3)
         DCL        VAR(&DREDATE) TYPE(*CHAR) STG(*DEFINED) +
                      LEN(7) DEFVAR(&DATERANGE 10)

         DCL        VAR(&TRANSTYPE) TYPE(*CHAR) LEN(9)

         if (&onelmcnt *ne 0) do
           /* ORDERNUM parameter has been entered */
         enddo

         if (&invdate *ne '0000000') do
           /* INVDATE parameter has been entered */
         enddo

         if (&drelmcnt *ne 0) do
           /* DATERANGE parameter has been entered */
         enddo

         if (&transtype *ne ' ') do
         enddo

done:   endpgm 

请注意混合列表(ELEM)参数的结构。如果列表中的元素数为0,则这些结构中只有元素计数&xxelmcnt字段有效。另请注意,这些字段将始终包含0或2(每个列表中已定义元素的数量)。如果提供了ORDERNUM参数,即使托运人编号留空,也会包含2。在这种情况下,为托运人编号传递的值将为0.

您可以在RPG程序中以类似的方式处理:

   ctl-opt Main(testcmd);

   dcl-ds ordernum_t qualified template;
     elements      Int(5);
     order         Packed(6:0);
     shipper       Packed(2:0);
   end-ds;

   dcl-ds daterange_t qualified template;
     elements      Int(5);
     begindt       Char(7);
     enddt         Char(7);
   end-ds;

   dcl-proc testcmd;
     dcl-pi *n ExtPgm('TESTCMD');
       ordernum      LikeDs(ordernum_t) const;
       invdate       Char(7) const;
       daterange     LikeDs(daterange_t) const;
       transtype     Char(9) const;
     end-pi;

     if ordernum.elements <> 0;
       // parameter has been entered
     endif;

     if invdate <> '0000000';
       // parameter has been entered
     endif;

     if daterange.elements <> 0;
       // parameter has been entered
     endif;

     if transtype <> '';
       // parameter has been entered
     endif;

     return;
   end-proc;

Here是关于如何处理混合列表参数的一些文档。在手册中包含它是简单列表的描述,以及列表中的列表(非常复杂)。

正如Charles所指出的那样,

编辑,您试图在示例中将参数值作为单个块进行访问。这几乎可以保证引起混淆,因为除了程序中定义的参数引用之外,没有关于如何将参数加载到内存中的(公共)定义。参数通过引用传递,调用程序确定它们在内存中的位置。假设每个参数在物理上与前一个参数相邻可能是一个危险的假设。访问给定参数的唯一安全方法是使用其单独的参数引用。尝试从参数1的参考中访问参数2是一个坏主意。即使工作一次,也不一定总能奏效。如您所见,命令对象根据用户键在内存中移动内容。

由于我们知道上面的命令定义了4个参数,即4 PARM个元素,我们可以确信4个参数中的每个参数都将完全按照命令中的定义传递给命令处理程序。 。但是,我们无法对内存中任何参数之后的内容充满信心。

答案 1 :(得分:2)

此处记录了PASSATR Pass attribute byte (PASSATR)

<强> *是
使用参数传递属性字节。 属性字节有两个字段:

  1. 属性字节的最左边一位表示是否指定了值。如果最左边的位是&#39; 0&#B; B,则传递给命令处理程序的值是默认值,并且未在命令字符串中指定。如果最左边的位是&#39; 1,则在命令字符串中指定传递给命令处理程序的值。
  2. 其余七位描述当为Type of value(TYPE)参数指定* CHAR时传递给命令处理程序的值。
  3. Attribute Description ---------- -------------------------------------- '0000010'B Meets *NAME rules, like A_B '0000100'B Meets GENERIC rules, like AB '1000101'B Quoted character string, like 'A B' '0000101'B Unquoted character string, like 5A '1001000'B Logical constant, '0' or '1' '0001100'B Hexadecimal value, like X'C1C2' '0100001'B Unsigned numeric value, like 5 '0101001'B Unsigned numeric with decimal point, like 5.2 '0110001'B Signed numeric value, like -5 '0111001'B Signed numeric with decimal point, like -5.2

    如果未指定(PASSVAL),请查看要传递的值,该文档位于PASSATR下方。

      

    未指定时传递的值(PASSVAL)
      指定值是否为   传递给该参数的命令处理程序。 * NULL是   如果参数是常量参数(参数中的参数),则无效   已为Constant值指定了一个值(CONSTANT)   参数,或* ZEROELEM或* NULL的参数   为值类型(TYPE)参数或列表/限定条件指定   由所有常量ELEM或QUAL语句定义的名称)。 *也是NULL   如果在返回值(RTNVAL)上指定了* YES,则无效   参数,或者为所需的最小值指定的值   (MIN)参数大于零。 DEP声明或REL和   其他PARM语句的RANGE关键字可能不指代的值   用* NULL定义的参数。

    如果PASSVAL未指定参数为* NULL,您应该能够在RPGLE中将其定义为OPTION(*OMIT),然后检查if %addr(myOptParm) <> 0;

    修改
    您尝试做的事情,将所有参数作为一个块传递是一个坏主意。您可能今​​天可以使用它,但它可能会因PTF的应用程序或操作系统升级而中断。该系统旨在传递单个参数。

    将它们全部传递给您的RPG程序并检查实际使用的内容。

答案 2 :(得分:0)

我模糊地回忆起Bob Cozzi的一篇文章,其中谈到了PASSATR属性。也许它会有所帮助... https://www.mcpressonline.com/programming/rpg/retrieving-user-space-data