我需要创建一个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变量的大小与接收源相同,以确保您可以接收返回的任何值。