PDA

View Full Version : Prozeduraufruf mit *OMIT-Parameter fehlerhaft



Fuerchau
21-05-20, 10:46
Vielleicht kann dies von euch einer nachvollziehen und ggf. einen Fehler an die IBM melden:
Fehlerbeschreibung V7R3:

// Deklaration
dcl-pr MyProc1 varchar(500);
Parm1 varchar(100) const;
Parm2 varchar(200) const options(*omit);
end-pr;

dcl-pr MyProc2 varchar(500);
Parm1 varchar(100) const;
Parm2 varchar(200) const options(*omit);
end-pr;

//Aufruf
MyProc1('Parameter1':'Parameter2');

// Verarbeitung (frag mich nicht warum, der Kunde macht es leider so)
dcl-proc MyProc1;
dcl-pi MyProc1 varchar(500);
Parm1 varchar(100) const;
Parm2 varchar(200) const options(*omit);
end-pi;
dcl-s RetVal varchar(500);

RetVal = MyProc2(Parm1:Parm2);
// Verarbeitung
:
// 2. Aufruf
RetVal = MyProc2(Parm1);

end-proc;

dcl-proc MyProc2;
dcl-pi MyProc1 varchar(500);
Parm1 varchar(100) const;
Parm2 varchar(200) const options(*omit);
end-pi;

// beim 2. Aufruf ist der Parameter nicht mehr NULL!!!
if %addr(Parm2) = *null;
endif;
end-proc;

Ich denke mal, dass bei *OMIT, falls es die letzten Parameter sind, die %parms() abzufragen sind sonst gibts Schrott.

B.Hauser
21-05-20, 11:45
Works as designed!
Was mich viel eher wundert, dass das Programm überhaupt kompiliert werden konnte!
Der 2. Parameter muss eigentlich übergeben werden.
Options(*OMIT) bedeutet, dass an dieser Stelle bei "nicht übergeben" der Sonderwert *OMIT übergeben werden muss!
Optionale Parameter werden mit OPTIONS(*NOPASS) definiert.
Aber auch dann sollte in der aufgerufenen Prozedur immer abgeprüft werden, ob der Parameter (überhaupt) übergeben wurde oder nicht. Wird ein nicht übergebener Parameter angesprochen erfolgt ein Abbruch (MCH3601).

Rainer Ross
21-05-20, 11:56
Hallo Baldur,
ich habe 7.3 und konnte, wie es Birgitta schon geschrieben hat, nicht kompilieren. Erst mit der Angabe RetVal = MyProc2(Parm1:*omit); lief der Compile ohne Fehler. Anbei das Program mit dem es ohne diesen von dir beschriebenen Fehler funktioniert hat



ctl-opt main(main) dftactgrp(*no);
//------------------------------------------------------------------//
// //
// Test - Procedure mit *omit //
// //
//----------------- //
// R.Ross 05.2020 * //
//------------------------------------------------------------------//
// MyProc1 //
//------------------------------------------------------------------//

dcl-pr MyProc1 varchar(500);
Parm1 varchar(100) const;
Parm2 varchar(200) const options(*omit);
end-pr;

//------------------------------------------------------------------//
// MyProc1 //
//------------------------------------------------------------------//

dcl-pr MyProc2 varchar(500);
Parm1 varchar(100) const;
Parm2 varchar(200) const options(*omit);
end-pr;

//------------------------------------------------------------------//
// Main //
//------------------------------------------------------------------//
dcl-proc main;

MyProc1('Parameter1':'Parameter2');

end-proc;
//------------------------------------------------------------------//
// MyProc1 //
//------------------------------------------------------------------//
dcl-proc MyProc1;
dcl-pi *n varchar(500);
Parm1 varchar(100) const;
Parm2 varchar(200) const options(*omit);
end-pi;

dcl-s RetVal varchar(500);

RetVal = MyProc2(Parm1:Parm2);

RetVal = MyProc2(Parm1:*omit);

return RetVal;

end-proc;
//------------------------------------------------------------------//
// MyProc2 //
//------------------------------------------------------------------//
dcl-proc MyProc2;
dcl-pi *n varchar(500);
Parm1 varchar(100) const;
Parm2 varchar(200) const options(*omit);
end-pi;

dcl-s RetVal varchar(500);

if %addr(Parm2) = *null;
endif;

return RetVal;

end-proc;
//------------------------------------------------------------------//

camouflage
21-05-20, 13:31
Anmerkung noch von mir: Eine %parms-Abfrage würde bei *omit fehlschlagen, da die Parameter bei *omit mitgezählt werden. Insofern ist die Abfrage %addr Null/notNull schon richtig.

Fuerchau
21-05-20, 17:08
Nun ja man sollt nicht immer alles unterschlagen. *NOPASS ist ebenso angegeben.
*OMIT bei der Übergabe wird als NULL-Pointer übergeben, deshalb muss man mit %addr() prüfen, ob eine Adresse gesetzt ist, sonst gibts wie immer den MCH.

Allerdings ist hier nicht so sehr das Problem der fehlenden Übergabe als dass beim 2. Aufruf der Parameter mit einer invaliden Adresse, also auf Müll zeigt, durch den vorherigen Aufruf besetzt ist.
Bei *NOPASS reicht daher die Abfrage auf %ADDR() = *NULL hier nicht mehr.
%parms() ist hier Pflicht.

camouflage
21-05-20, 17:36
Der *omit auf der letzten Position ist eh sinnlos, Doppelmord im Schlüsselloch. Da reicht ein *nopass. Aber man kann sich auch Probleme aufhalsen, die eigentlich nicht sein müssten. In deinem Fall hast Du natürlich recht.

B.Hauser
21-05-20, 18:30
%Parms muss immer geprüft werden, wenn mit *NOPASS gearbeitet wird!