如何创建一个接受不同长度的十进制参数的AS/400命令



我需要创建一个AS/400命令。该命令有一个十进制类型的参数,用于从它的命令处理程序(一个RPGLE程序)向CL变量返回一个值。最初,返回的十进制值的长度应该是10,小数点后0位,这很容易做到,因为CL变量的长度也是固定的。现在,我的老板想要增强这个命令,以便这个参数可以将值返回到具有可变长度(小数点后0位)的CL变量,类似于RTVDTAARA命令在从十进制数据区域检索值时所做的事情。有人能告诉我怎么做吗?非常感谢。

更复杂的方法是创建一个类型为*X的形参。然后,您可以将任何类型的变量传递给您的RPGLE程序并处理它。你可以接受*CHAR, *DEC, *INT等等。下面是命令定义的一个示例PARM语句:

PARM       KWD(RTNVAR) TYPE(*X) LEN(1 10 0) +
             RTNVAL(*YES) MIN(1) VARY(*YES *INT2) +
             PASSATR(*YES) Prompt('Return Field')

如果您输入这个并单击帮助,它可以解释TYPE(*X)如何使用LEN属性以及VARY和PASSATR属性如何工作。对于本例,我为小数设置了默认值10,0,但它不一定是。

然后,在您的RPGLE程序中,获取该入口参数并将其分解为如下的数据结构:

D#EntryVariable   DS
D parmAttr1               1      1i 0
D parmNumDec              2      2i 0
D parmDecLength           3      3i 0
D parmSize                2      3i 0
D EntryValue              4     19

您可以将EntryValue设置为您认为最大的长度,请记住CL中的十进制变量以打包格式存储在内存中,因此15字节的十进制字段将是8字节长(7.5字节+ 0.5字节符号)。字段的数据结构细分如下:

  • parmAttr1告诉您传递的变量类型。以下是一些价值观:
    • *DEC = 0x03
    • *INT = 0x00
    • *CHAR = 0x04
  • parmNumDec仅对*DEC变量有效。它是小数的个数。
  • parmDecLength仅对*DEC变量有效。它是*DEC字段
  • 的总位数。
  • parmSize仅对非*DEC变量有效。是传递的变量的长度。
  • EntryValue是返回给调用程序的值。它将保存在调用命令之前的任何值。给它足够的空间来容纳你期望的多大的变量。

然后处理代码以检索值并将其放在数据结构的EntryValue部分中。更新EntryValue时要非常小心。超过传递长度的任何数据都不属于您的程序,如果您更改它,可能会破坏作业中的其他内容。同样,请记住CL十进制变量以打包的十进制格式存储在内存中。

要将十进制值填充到未知大小的填充字段中,有两种方法之一。简单但冗长的方法是创建15个不同的打包的十进制变量,并在条目参数数据结构中定义它们,使用SELECT和WHEN填充。另一种方法是使用指针和循环。我来告诉你怎么做。首先,需要定义一些指针和工作字段:

 *Working field to hold the value to be returned.
 *Decimal places are implied, but not necessary.
DworkDec          S             15P 0
 *Pointer to the value part of the entry parameter.
DptrParmValue     S               *
 *Pointer to the working decimal field.
DptrWorkDec       S               *
 *A single byte of the parm value. This will move along the
 *parm value field as ptrParmValue changes.
DparmChar         S              1    Based(ptrParmValue)
 *A single byte of the workDec field. This will move along
 *the field as ptrWorkDec changes.
DworkChar         S              1    Based(ptrWorkDec)
 *A counter for positioning the ptrParmValue pointer.
DparmPos          S              5i 0
 *A counter for positioning the ptrWorkDec pointer.
DworkPos          S              5i 0
 *The actual length, in bytes, of the return parm value
DparmRealLen      S              5i 0

您要做的是将结果值移动到workDec字段中。我建议创建一个临时整数字段(5i 0),并将结果乘以10的小数位数的幂,以获得一个带有隐含小数的整数,然后将临时整数字段EVAL为workDec。workDec被定义为15,0,因为这是CL十进制字段所能达到的最大值——请记住,我们在这里忽略了小数。所以我们知道workDec总是大于,或者等于传递的形参。

设置workDec后,您从workDec和parmValue的最右侧开始向后开始,随着您的前进而减少字节。这样做是因为打包后的十进制值在内存中以右对齐方式存储。

/free
 workPos = (%Size(workDec)+.5)/2 + .99 - 1;
 parmRealLen = (parmDecLength_.5)/2 + .99;
 For parmPos = parmRealLen-1 downTo 0;
   ptrParmValue = %Addr(parmValue)+parmPos;
   ptrWorkDec = %Addr(workDec)+workPos;
   parmChar = workChar;
   workPos = workPos-1;
 EndFor;
/end-free

james和X-Zero基本上已经涵盖了这一点,但要明确一点:CL程序和AS/400命令没有可变长度十进制类型的概念。你必须选择一个最大尺寸,就这样。

如果您实际尝试调用RTVDTAARA命令,您将看到您可以在调用CLP中使用任何大小的十进制变量来保存返回值。只有当返回值太大而无法容纳用来保存返回值的变量时,大小才会出现问题。

因此,例如,如果您有一个值为500的*DEC(10 0)数据区域,您可以使用RTVDTAARA将其值检索到任何*DEC类型的CL变量中,只要该变量大于等于(30)。如果数据区域的值为1000,则接收CL变量必须为(4 0)或更大。

从这个意义上讲,可变长度的十进制参数是内建的。标准做法是始终使接收CL变量的大小与接收源相同,以确保您可以接收返回的任何值。

相关内容

  • 没有找到相关文章

最新更新