Как создать команду AS / 400, которая принимает десятичный параметр различной длины? - PullRequest
0 голосов
/ 04 ноября 2011

Мне нужно создать команду AS / 400.Эта команда имеет параметр с десятичным типом, который используется для возврата значения переменной CL из ее программы обработки команд, которая является программой RPGLE.Первоначально длина возвращаемого десятичного значения должна иметь длину 10 с 0 десятичным разрядом, что было легко сделать, так как длина переменной CL также фиксирована.Теперь мой начальник хотел усовершенствовать эту команду, чтобы этот параметр мог возвращать значение переменной CL, имеющей переменную длину (все еще 0 десятичных знаков), аналогично тому, что команда RTVDTAARA может делать при получении значения из области десятичных данных.Может кто-нибудь сказать мне, как сделать эту работу?Большое спасибо.

Ответы [ 2 ]

2 голосов
/ 08 ноября 2011

Более сложный способ сделать это - создать параметр типа * 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 байт +. 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 до степени количества десятичных позиций в результате, чтобы получить целое число с подразумеваемым десятичным числом, а затем СДЕЛАТЬ временное целочисленное поле в 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
1 голос
/ 04 ноября 2011

JamesA и X-Zero в основном рассмотрели это, но для ясности: программы CL и команды AS / 400 не имеют представления о десятичном типе переменной длины.Вы должны выбрать максимальный размер, и все.

Если вы действительно попытаетесь вызвать команду RTVDTAARA, после которой вы пытаетесь смоделировать свою команду, вы увидите, что вы можете использовать любую десятичную переменную размера ввызов CLP для хранения возвращаемого значения.Единственная ситуация, в которой размер является проблемой, - это когда возвращаемое значение слишком велико, чтобы соответствовать переменной, предназначенной для хранения возвращаемого значения.

Так, например, если у вас есть * DEC (10 0) область данных со значением 500, вы можете извлечь ее значение с помощью RTVDTAARA в любую переменную CL типа * DEC, если эта переменная (3 0) или больше.Если область данных имеет значение 1000, получающая переменная CL должна быть (4 0) или больше.

В этом смысле, десятичные параметры переменной длины являются своего рода встроенными. Стандартная практика состоит в том, чтобы всегдасделайте получающую переменную CL того же размера, что и получаемый вами, чтобы гарантировать, что вы можете получить любое возвращаемое значение.

...