在 RPGLE 程序中添加新的入口参数
Adding new entry parameter in an RPGLE program
我正在修改这个非常关键的 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;
代码中使用此参数的唯一其他区域如上所示。在这里,我确保在引用参数之前,检查参数是否已传递。
我已经测试过,效果很好。但是,考虑到应用的重要性,还是想到了寻求高手的帮助。
欢迎任何关于此的guidance/suggestions。
据我所知,RPG 将调用者的参数视为 "Do what you want"。这意味着如果 PGM01 被 PGM02 调用,其中 PGM1 接受 3 个参数,而 PGM2 调用带有 3 个参数,一切都很好。当 PGM01 想要 3 个参数而 PGM02 给了 2 个参数时,你可以这样做。但是你必须注意如果第三个参数是 *NULL(就像你所做的那样)会发生什么。如果您使用 4 个参数调用 PGM01,而 PGM01 仅 "wants" 3 个,则没有问题,因为 PGM01 不关心这些。
但我会保留 *ENTRY 样式,而是使用原型。在那里您可以定义如果参数是可省略的,则可以使用该参数但不是必须的。请阅读 D-Spec
和 PR
关键字的手册。
您有内存损坏错误等待发生...
如果您尝试在没有最后一个参数的情况下调用该程序并且它似乎成功了,那么您只是幸运地没有使用内存区域......因此是零并且您的 %Addr(E_Grp) <> *NULL
按预期工作。
为了进行比较 %Addr(E_Grp) <> *NULL
您的调用程序必须为该参数传递 *OMIT
特殊值。显然,这需要更改所有调用程序。
你想要的是不必更改调用程序,因此你需要在被调用程序中将参数设置为 *NOPASS
。
您应该转换为调用程序以使用 PR/PI 而不是 *ENTRY PLIST。然后你可以将最后一个参数标记为options(*NOPASS *OMIT)
然后在被调用的程序中,可以勾选
- 如果传递了参数
- 如果传递的参数为 NULL (*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;
我正在修改这个非常关键的 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;
代码中使用此参数的唯一其他区域如上所示。在这里,我确保在引用参数之前,检查参数是否已传递。
我已经测试过,效果很好。但是,考虑到应用的重要性,还是想到了寻求高手的帮助。
欢迎任何关于此的guidance/suggestions。
据我所知,RPG 将调用者的参数视为 "Do what you want"。这意味着如果 PGM01 被 PGM02 调用,其中 PGM1 接受 3 个参数,而 PGM2 调用带有 3 个参数,一切都很好。当 PGM01 想要 3 个参数而 PGM02 给了 2 个参数时,你可以这样做。但是你必须注意如果第三个参数是 *NULL(就像你所做的那样)会发生什么。如果您使用 4 个参数调用 PGM01,而 PGM01 仅 "wants" 3 个,则没有问题,因为 PGM01 不关心这些。
但我会保留 *ENTRY 样式,而是使用原型。在那里您可以定义如果参数是可省略的,则可以使用该参数但不是必须的。请阅读 D-Spec
和 PR
关键字的手册。
您有内存损坏错误等待发生...
如果您尝试在没有最后一个参数的情况下调用该程序并且它似乎成功了,那么您只是幸运地没有使用内存区域......因此是零并且您的 %Addr(E_Grp) <> *NULL
按预期工作。
为了进行比较 %Addr(E_Grp) <> *NULL
您的调用程序必须为该参数传递 *OMIT
特殊值。显然,这需要更改所有调用程序。
你想要的是不必更改调用程序,因此你需要在被调用程序中将参数设置为 *NOPASS
。
您应该转换为调用程序以使用 PR/PI 而不是 *ENTRY PLIST。然后你可以将最后一个参数标记为options(*NOPASS *OMIT)
然后在被调用的程序中,可以勾选
- 如果传递了参数
- 如果传递的参数为 NULL (*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;