Добавление нового параметра ввода в программу RPGLE
Я модифицирую эту крайне критичную программу RPGLE, где изменения включают добавление в нее нового параметра ввода.
*entry plist
parm ecorp corp
parm edivi divi
parm eplvl parent lv
parm ewrsc wc rscd
parm eplnt plnt
parm eclvl child lv
parm emord ord
parm easst asst
parm emrwk mrwk#
parm eseqn seq #
parm easeq alt seq #
parm epprd alt seq #
parm eotst alt seq #
parm ewpqt alt seq #
parm ecmpc alt seq #
parm ewurs alt seq #
parm emurs alt seq #
parm epcdt alt seq #
parm E_Optn option
parm eeoj end of job
parm E_Pgm program
parm E_GRP MO GROUP
Список параметров записи программы такой же, как и выше, за исключением последнего параметра, который я добавил сейчас. Программа работает отлично. Но меня немного беспокоит, если это как-то повлияет на другие области, откуда эта программа называется. программы вызова, где последний параметр ввода не передается.
Этот новый входной параметр будет передаваться только из одной другой программы, которая является частью изменения. Существует довольно много других программ, которые будут вызывать программу, передающую тот же список параметров, что и ранее.
If (%Addr(E_Grp) <> *NULL);
Chain (E_Grp:EWURS:ssmurs) MFMPP00;
If %Found();
MchAllotted = *On;
Leave;
EndIf;
EndIf;
Единственная другая область в коде, где используется этот параметр, показана выше. Здесь я убедился, что перед ссылкой на параметр проверяется, что параметр передан.
Я проверил, и это прекрасно работает. Однако, учитывая критичность приложения, все же подумал, что нужно обратиться за помощью к специалисту.
Любые указания / предложения по этому вопросу приветствуются.
3 ответа
У вас есть ошибка повреждения памяти, ожидающая...
Если вы пытались вызвать программу без последнего параметра, и она, кажется, сработала, вам просто повезло, что область памяти не использовалась... таким образом, были нули и ваша %Addr(E_Grp) <> *NULL
работал как положено.
Для сравнения %Addr(E_Grp) <> *NULL
Ваши вызывающие программы должны пройти *OMIT
специальное значение для этого параметра. Очевидно, что это потребует изменения всех вызывающих программ.
Вам не нужно менять вызывающие программы, поэтому в вызываемой программе вам нужно, чтобы параметр был *NOPASS
,
Вы должны преобразовать в вызываемую программу, чтобы использовать PR/PI вместо *ENTRY PLIST. Тогда вы можете пометить последний параметр как options(*NOPASS *OMIT)
Затем в вызываемой программе вы можете проверить
- если параметр был передан
- если переданный параметр был НЕДЕЙСТВИТЕЛЕН (* ПУСК)
Код
// check if the parm was passed
if %parms() > = %parmnum(E_GRP);
// check if passed parm is not NULL
if %Addr(E_Grp) <> *NULL;
//ok to use E_Grp
Chain (E_Grp:EWURS:ssmurs) MFMPP00;
If %Found();
MchAllotted = *On;
Leave;
endif;
endif;
endif;
Если параметр не будет изменен в программе, то более безопасный способ его использования - инициализация переменной по умолчанию, а при передаче параметра скопируйте параметр в эту переменную. Таким образом, если будет добавлено больше кода, использующего значение параметра, им не нужно будет забывать добавить проверку.
... Change the name of E_GRP parameter to E_GRP_parm
dcl-s E_GRP ... INZ(whatever);
if %parms() >= %parmnum(E_GRP_parm);
E_GRP = E_GRP_parm;
endif;
Вы также можете использовать эту технику с измененным параметром:
dcl-pi *n;
something_parm char(10) OPTIONS(*NOPASS);
end-pi;
dcl-s something char(10) INZ('Whatever');
// Get the value of the "someThing" parameter if it was passed
if %parms() >= %parmnum(something_parm);
someThing = someThing_parm;
endif;
...
// Update the "someThing" parameter if it was passed
if %parms() >= %parmnum(someThing_parm);
someThing_parm = someThing;
endif;
Насколько я знаю, RPG рассматривает параметры от вызывающего как "Делай, что хочешь". Это означает, что если PGM01 вызывается PGM02, где PGM1 принимает 3 параметра, а вызовы PGM2 с 3 параметрами, то все в порядке. Когда PGM01 хочет 3 параметра, а PGM02 дает 2 параметра, вы можете сделать это. Но вы должны позаботиться о том, что произойдет, если третий параметр *NULL (как вы делаете). Если вы вызываете PGM01 с 4 параметрами, тогда как PGM01 только "хочет" 3, проблема не возникает, поскольку PGM01 не заботится об этом.
Но я бы оставил стиль *ENTRY и использовал бы прототипы. Там вы можете определить, что, если параметр опускается, параметр может использоваться, но не обязательно. Пожалуйста, прочитайте руководство для D-Spec
и PR
ключевое слово.