Interception d’une erreur non prévue
lun 11 février 2019Vous reconnaissez-vous sur la photo ? C’est lors de votre dernier plantage en production, le fameux « Exception and Error Handling » d’IBM, Vous avez l’utilisateur au téléphone qui vous dit :
« J'ai eu un plantage!
- OK, qu'avez-vous fait?
- l'écran m'a demandé de répondre C D G ou F.
- Et qu'avez-vous saisi?
- J'ai saisi C »; vous dit-il fièrement.
Pour vous aider à ne plus vous retrouver face à cette situation, voici quelques idées pour maîtriser l’interception de ces plantages et une sous-procédure pour exprimer ces erreurs.
Les idées
CLP, CLLE
Le code ci-dessous placé dans une sous-routine permet d’intercepter et générer des informations nécessaires à l’analyse de l’erreur sans « planter » le travail. La sous-procédure Gest_erreur sert à compiler les informations et à avertir qui de droit. Elle sera expliquée plus loin dans cet article.
PGM
DCL VAR(&PGM) TYPE(*CHAR) LEN(10) VALUE('TESTPGM1')
CPYF FROMFILE(TESTFILE) TOFILE(TESTFILEH) MBROPT(*ADD)
MONMSG MSGID(CPF0000) EXEC(CALLSUBR SUBR(ERROR))
----
----
/*==========================================================*/
SUBR(ERROR)
DMPCLPGM
CALLPRC PRC(GEST_ERREUR)
ENDSUBR
/*==========================================================*/
ENDPGM
Figure 1
Nous pouvons décider d’arrêter le programme et redonner le contrôle à l’appelant en déplaçant l’interception d’erreur en fin de programme.
PGM PARM(&BIB &NEWPROP &CUROWNAUT)
DCL VAR(&BIB) TYPE(*CHAR) LEN(10)
DCL VAR(&NEWPROP) TYPE(*CHAR) LEN(10)
DCL VAR(&CUROWNAUT) TYPE(*CHAR) LEN(10)
DCLF FILE(DSPOBJDL)
MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERREUR))
DSPOBJD OBJ(&BIB/*ALL) OBJTYPE(*ALL) +
OUTPUT(*OUTFILE) OUTFILE(QTEMP/DSPOBJDL)
LECTURE: RCVF
MONMSG MSGID(CPF0864) EXEC(GOTO CMDLBL(FIN))
CHGOBJOWN OBJ(&BIB/&ODOBNM) OBJTYPE(&ODOBTP) +
NEWOWN(&NEWPROP) CUROWNAUT(&CUROWNAUT)
RETURN
ERREUR: DMPCLPGM
CALLPRC PRC(GEST_ERREUR)
FIN: ENDPGM
Figure 2
RPG, RPG ile
Carte H ou spécifications de contrôles
Pour avoir les meilleurs chances possibles de notre côté, nous allons amender les spécifications de contrôles (Fig. 3):
- L’option *srcstmt est très utile, lors d’une remontée d’erreur, la ligne indiquée en erreur est le numéro de ligne du source à la place de celle de listing de compilation.
- Le mot debug n’est pas obligatoire, dans ce cas la commande dump prend l’option (a) : dump(a).
Plusieurs méthodes d’interception d’erreur sont possibles : *PSSR ou le groupe MONITOR.
*PSSR
La sous-routine *PSSR est appelé quand une erreur non interceptée se produit. Il est préférable d’utiliser l’opération MONITOR dans la programmation moderne. *PSSR est à utiliser dans le cas de programme utilisant le cycle (GOTO ou les tags). Toutefois ces programmes existent et fonctionnent toujours, il est donc nécessaire de connaître ce moyen.
H Option(*srcstmt) debug
| | | | | | | | | | | | | |
c *pssr BEGSR
c dump
c callp gest_erreur()
c ENDSR
Figure 3
Groupe MONITOR
Aujourd’hui, la méthode préconisée par IBM est le groupe MONITOR.
hdebug(*yes) datfmt(*eur) bnddir('SERVICE') option(*srcstmt)
| |
/free
monitor;
| |
| |
on-error;
dump;
gest_erreur();
endmon;
Mais vous ne pouvez pas utiliser Monitor quand des opérations tel que goto existent.
Figure 4
Expression des anomalies
Après avoir vu comment intercepter les erreurs, nous allons voir GEST_ERREUR qui gère la restitution des informations qui va vous permettre d’analyser le problème rencontré par l’utilisateur.
L’outil est constitué de 2 sous-procédures, fig.5 vous montre le source de liage.
STRPGMEXP PGMLVL(*CURRENT)
EXPORT SYMBOL(GEST_ERREUR)
EXPORT SYMBOL(MAILERR)
ENDPGMEXP
Figure 5
Gest_erreur
La sous-procédure gest-erreur présente 2 fonctionnements selon que le travail est interactif ou batch.
Gest_erreur comporte trois étapes.
- Il édite un résumé de l’erreur.
- Si le travail est un batch, il édite l’écran sur lequel l’utilisateur se trouvait quand l’erreur a eu lieu.
- Il extrait les adresses email de destination.
h nomain debug
* Déclaration des fichiers
fMailInfol2if e k disk USROPN
FERRORLST O e printer
F USROPN
F OFlInd(OverFlow)
* Déclaration de le PSDS
d*copy qcpysrc,CPY_PSDS
*
* Copie API
/Copy qcpysrc,STDMSGINFO
* Programme data structure
D HlpText DS
D HlpText01
D HlpText02
D HlpText03
D HlpText04
D HlpText05
D HlpText06
D HlpText07
D HlpText08
D HlpText09
D HlpText10
D ScreenIn DS
D Row8001 OverLay(ScreenIn:1)
D Row8002 OverLay(ScreenIn:*Next)
D Row8003 OverLay(ScreenIn:*Next)
D Row8004 OverLay(ScreenIn:*Next)
D Row8005 OverLay(ScreenIn:*Next)
D Row8006 OverLay(ScreenIn:*Next)
D Row8007 OverLay(ScreenIn:*Next)
D Row8008 OverLay(ScreenIn:*Next)
D Row8009 OverLay(ScreenIn:*Next)
D Row8010 OverLay(ScreenIn:*Next)
D Row8011 OverLay(ScreenIn:*Next)
D Row8012 OverLay(ScreenIn:*Next)
D Row8013 OverLay(ScreenIn:*Next)
D Row8014 OverLay(ScreenIn:*Next)
D Row8015 OverLay(ScreenIn:*Next)
D Row8016 OverLay(ScreenIn:*Next)
D Row8017 OverLay(ScreenIn:*Next)
D Row8018 OverLay(ScreenIn:*Next)
D Row8019 OverLay(ScreenIn:*Next)
D Row8020 OverLay(ScreenIn:*Next)
D Row8021 OverLay(ScreenIn:*Next)
D Row8022 OverLay(ScreenIn:*Next)
D Row8023 OverLay(ScreenIn:*Next)
D Row8024 OverLay(ScreenIn:*Next)
D Row13201 OverLay(ScreenIn:1)
D Row13202 OverLay(ScreenIn:*Next)
D Row13203 OverLay(ScreenIn:*Next)
D Row13204 OverLay(ScreenIn:*Next)
D Row13205 OverLay(ScreenIn:*Next)
D Row13206 OverLay(ScreenIn:*Next)
D Row13207 OverLay(ScreenIn:*Next)
D Row13208 OverLay(ScreenIn:*Next)
D Row13209 OverLay(ScreenIn:*Next)
D Row13210 OverLay(ScreenIn:*Next)
D Row13211 OverLay(ScreenIn:*Next)
D Row13212 OverLay(ScreenIn:*Next)
D Row13213 OverLay(ScreenIn:*Next)
D Row13214 OverLay(ScreenIn:*Next)
D Row13215 OverLay(ScreenIn:*Next)
D Row13216 OverLay(ScreenIn:*Next)
D Row13217 OverLay(ScreenIn:*Next)
D Row13218 OverLay(ScreenIn:*Next)
D Row13219 OverLay(ScreenIn:*Next)
D Row13220 OverLay(ScreenIn:*Next)
D Row13221 OverLay(ScreenIn:*Next)
D Row13222 OverLay(ScreenIn:*Next)
D Row13223 OverLay(ScreenIn:*Next)
D Row13224 OverLay(ScreenIn:*Next)
D Row13225 OverLay(ScreenIn:*Next)
D Row13226 OverLay(ScreenIn:*Next)
D Row13227 OverLay(ScreenIn:*Next)
* Prototypage fonction externe
d mail_erreur pr extproc(*cl : 'MAILERR')
d a_program like(r_nomobj)
d a_module like(r_nomobj)
d a_procedure 60
d a_statement like(r_nomobj)
d a_mail 320
* Prototypage fonctions locales
d gest_erreur pr
d adress_mail pr 320
d Comp_Adr pr 320
d reference 10
d mail s 320
* Héritages des types
d/copy QINHLESRC,INH32766
* Constantes
* Fonctions locales
p gest_erreur b export
d gest_erreur pi
* DS locales
* Variables locales
D MsgBack DS LikeDs(RCVM0300) Inz
D InfoPtr S *
D MsgInfo DS LikeDs(RCVM0300SndRcvInfo)
D Based(InfoPtr)
D i S 10I 0
D SetMsgKey S 4 Inz(*ALLx'00')
D BufferHandle S 10I 0
D BytesReturned S 10I 0
D DataPtr S *
D CatchScreen DS LikeDS(ScreenIn)
D Based(DataPtr)
* Fonction principale
/free
Monitor;
Open ErrorLst;
Open MailInfol2;
Write Head;
ReceiveMsg( MsgBack
: %size(MsgBack)
: 'RCVM0300'
: '*'
: 1
: '*PRV'
: SetMsgKey
: 0
: '*SAME'
: APIError);
If MsgBack.ByteAvail > 0;
MsgText = %SubSt(MsgBack.MsgData:
MsgBack.LenReplace1 + 1:
MsgBack.LenMsgReturn);
HlpText = %SubSt(MsgBack.MsgData:
MsgBack.LenReplace1 +
MsgBack.LenMsgReturn + 1:
MsgBack.LenHelpReturn);
InfoPtr = %Addr(MsgBack.MsgData)
+ MsgBack.LenReplace1
+ MsgBack.LenMsgReturn
+ MsgBack.LenHelpReturn;
Program = MsgInfo.ReceivingPgm;
Module = MsgInfo.ReceivingModule;
Proced = MsgInfo.ReceivingProcedure;
Statement = MsgInfo.StateNosReceiving;
Write Detail;
If OverFlow;
Write Head;
OverFlow = *Off;
EndIf;
EndIf;
BufferHandle = CreateInputBuffer( 27 * 132
: *Omit
: *Omit
: *Omit
: APIError );
If APIError.BytesAvail = 0;
BytesReturned = ReadScreen( *Omit
: BufferHandle
: *Omit
: *Omit
: *Omit );
DataPtr = RetrieveDataPtr( BufferHandle
: *Omit
: *Omit );
ScreenIn = %SubSt(CatchScreen:1:BytesReturned);
For i = 1 to BytesReturned;
If (%SubSt(ScreenIn:i:1) > x'19') And
(%SubSt(ScreenIn:i:1) < x'40');
%SubSt(ScreenIn:i:1) = *Blank;
EndIf;
EndFor;
If BytesReturned = 1920;
Write Screen80;
Else;
Write Screen132;
EndIf;
EndIf;
Write Footer;
mail=adress_mail();
Close ErrorLst;
Close MailInfol2;
mail_erreur( program
: module
: proced
: statement
: mail);
return;
On-error *all;
dsply 'Arrrrgghhhh!!!!';
endmon;
/end-free
p gest_erreur e
p adress_mail b
d adress_mail pi 320
* Variables locales
d l_Adress_Mail s 320
/free
reference=program;
setll reference mailinfol2;
if %equal();
l_Adress_Mail=Comp_Adr(reference);
else;
reference='defaut';
setll reference mailinfol2;
if %equal();
l_Adress_Mail=Comp_Adr(reference);
endif;
endif;
return l_Adress_Mail;
/end-free
p adress_mail e
p Comp_Adr b
d Comp_Adr pi 320
d reference 10
* Variables locales
d ds
d l_Adress_Mail 320
d t_Adress_Mail 32 dim(10)
d overlay(l_Adress_Mail)
d i s 3 0
/free
reset l_adress_mail;
reade reference mailinfol2;
i=0;
dow not %eof();
i+=1;
t_adress_mail(i)=AdrMail;
reade reference mailinfol2;
enddo;
return l_adress_mail;
/end-free
p Comp_Adr e
Figure 6
Mailer
Mailer :
- génère la joblog,
- concatène le résumé, le dump et la joblog,
- constitue l’édition sous format pdf,
- envoi le pdf par mél.
PGM PARM(&PROGRAM &MODULE &PROCEDURE &ERROR &ADRINFO)
DCLF FILE(FGESTERR)
DCL VAR(&OBJET) TYPE(*CHAR) LEN(44)
DCL VAR(&DEST1) TYPE(*CHAR) LEN(36)
DCL VAR(&DEST2) TYPE(*CHAR) LEN(36)
DCL VAR(&DEST3) TYPE(*CHAR) LEN(36)
DCL VAR(&DEST4) TYPE(*CHAR) LEN(36)
DCL VAR(&DEST5) TYPE(*CHAR) LEN(36)
DCL VAR(&DEST6) TYPE(*CHAR) LEN(36)
DCL VAR(&DEST7) TYPE(*CHAR) LEN(36)
DCL VAR(&DEST8) TYPE(*CHAR) LEN(36)
DCL VAR(&DEST9) TYPE(*CHAR) LEN(36)
DCL VAR(&DEST10) TYPE(*CHAR) LEN(36)
DCL VAR(&MSG_ERR) TYPE(*CHAR) LEN(2000)
DCL VAR(&JOBTYP) TYPE(*CHAR) LEN(1) /* Type de +
travail 0 => Batch 1=> interactif */
/* Email contact */
DCL VAR(&ADRINFO) TYPE(*CHAR) LEN(320)
/* PARAMETRE D'APPELS PARAMETRABLE */
DCL VAR(&MAILADR) TYPE(*CHAR) LEN(50)
DCL VAR(&ADRMAIL) TYPE(*CHAR) LEN(320)
DCL VAR(&CMD) TYPE(*CHAR) LEN(500)
DCL VAR(&LNG) TYPE(*DEC) LEN(15 5) VALUE(500)
DCL VAR(&MSG) TYPE(*CHAR) LEN(512)
DCL VAR(&MSGID) TYPE(*CHAR) LEN(7)
DCL VAR(&MSGF) TYPE(*CHAR) LEN(10)
DCL VAR(&MESSAGE) TYPE(*CHAR) LEN(2000)
DCL VAR(&ADRPIECJOI) TYPE(*CHAR) LEN(150)
DCL VAR(&SYSTEM) TYPE(*CHAR) LEN(8)
DCL VAR(&EMET) TYPE(*CHAR) LEN(30)
DCL VAR(&SUJET) TYPE(*CHAR) LEN(200)
DCL VAR(&PROCEDURE) TYPE(*CHAR) LEN(60)
CHGVAR VAR(&PROCED1) VALUE(%SST(&PROCEDURE 1 30))
CHGVAR VAR(&PROCED2) VALUE(%SST(&PROCEDURE 31 30))
CHGVAR VAR(&DEST1) VALUE('(''' *TCAT %SST(&ADRINFO +
1 32) *TCAT ''')')
IF COND(%SST(&ADRINFO 33 32) *NE ' ') +
THEN(CHGVAR VAR(&DEST2) VALUE('(''' *TCAT +
%SST(&ADRINFO 33 32) *TCAT ''')'))
IF COND(%SST(&ADRINFO 65 32) *NE ' ') +
THEN(CHGVAR VAR(&DEST3) VALUE('(''' *TCAT +
%SST(&ADRINFO 65 32) *TCAT ''')'))
IF COND(%SST(&ADRINFO 97 32) *NE ' ') +
THEN(CHGVAR VAR(&DEST4) VALUE('('''' +
*TCAT %SST(&ADRINFO 97 32) *TCAT '''')'))
IF COND(%SST(&ADRINFO 129 32) *NE ' ') +
THEN(CHGVAR VAR(&DEST5) VALUE('('''' +
*TCAT %SST(&ADRINFO 129 32) *TCAT '''')'))
IF COND(%SST(&ADRINFO 161 32) *NE ' ') +
THEN(CHGVAR VAR(&DEST6) VALUE('('''' +
*TCAT %SST(&ADRINFO 161 32) *TCAT '''')'))
IF COND(%SST(&ADRINFO 193 32) *NE ' ') +
THEN(CHGVAR VAR(&DEST7) VALUE('('''' +
*TCAT %SST(&ADRINFO 193 32) *TCAT '''')'))
IF COND(%SST(&ADRINFO 224 32) *NE ' ') +
THEN(CHGVAR VAR(&DEST8) VALUE('('''' +
*TCAT %SST(&ADRINFO 224 32) *TCAT '''')'))
IF COND(%SST(&ADRINFO 256 32) *NE ' ') +
THEN(CHGVAR VAR(&DEST9) VALUE('('''' +
*TCAT %SST(&ADRINFO 256 32) *TCAT '''')'))
IF COND(%SST(&ADRINFO 288 32) *NE ' ') +
THEN(CHGVAR VAR(&DEST10) VALUE('('''' +
*TCAT %SST(&ADRINFO 288 32) *TCAT '''')'))
CHGVAR VAR(&ADRMAIL) VALUE(&DEST1)
IF COND(&DEST2 *NE ' ') THEN(CHGVAR +
VAR(&ADRMAIL) VALUE(&ADRMAIL *BCAT &DEST2))
IF COND(&DEST3 *NE ' ') THEN(CHGVAR +
VAR(&ADRMAIL) VALUE(&ADRMAIL *BCAT &DEST3))
IF COND(&DEST4 *NE ' ') THEN(CHGVAR +
VAR(&ADRMAIL) VALUE(&ADRMAIL *BCAT &DEST4))
IF COND(&DEST5 *NE ' ') THEN(CHGVAR +
VAR(&ADRMAIL) VALUE(&ADRMAIL *BCAT &DEST5))
IF COND(&DEST6 *NE ' ') THEN(CHGVAR +
VAR(&ADRMAIL) VALUE(&ADRMAIL *BCAT &DEST6))
IF COND(&DEST7 *NE ' ') THEN(CHGVAR +
VAR(&ADRMAIL) VALUE(&ADRMAIL *BCAT &DEST7))
IF COND(&DEST8 *NE ' ') THEN(CHGVAR +
VAR(&ADRMAIL) VALUE(&ADRMAIL *BCAT &DEST8))
IF COND(&DEST9 *NE ' ') THEN(CHGVAR +
VAR(&ADRMAIL) VALUE(&ADRMAIL *BCAT &DEST9))
IF COND(&DEST10 *NE ' ') THEN(CHGVAR +
VAR(&ADRMAIL) VALUE(&ADRMAIL *BCAT &DEST10))
DSPJOBLOG OUTPUT(*PRINT)
RTVJOBA JOB(&JOB_NAME) USER(&USER) NBR(&JOB_NUM) +
TYPE(&JOBTYP)
RTVNETA SYSNAME(&SYSTEM)
IF COND(&JOBTYP *EQ '1') THEN(DO)
FENETRE: SNDRCVF
IF COND(&IN05) THEN(GOTO CMDLBL(MAIL))
ELSE CMD(GOTO CMDLBL(FENETRE))
ENDDO
MAIL: CHKOBJ OBJ(QTEMP/DUMP) OBJTYPE(*FILE)
MONMSG MSGID(CPF9801) EXEC(CRTPF FILE(QTEMP/DUMP) +
RCDLEN(132) SIZE(*NOMAX))
CHKOBJ OBJ(QTEMP/ERRORLST) OBJTYPE(*FILE)
MONMSG MSGID(CPF9801) EXEC(CRTPF FILE(QTEMP/ERRORLST) +
RCDLEN(132) SIZE(*NOMAX))
CHKOBJ OBJ(QTEMP/QPJOBLOG) OBJTYPE(*FILE)
MONMSG MSGID(CPF9801) EXEC(CRTPF FILE(QTEMP/QPJOBLOG) +
RCDLEN(132) SIZE(*NOMAX))
CPYSPLF FILE(ERRORLST) TOFILE(QTEMP/ERRORLST) +
JOB(&JOB_NUM/&USER/&JOB_NAME) SPLNBR(*LAST)
CPYSPLF FILE(QPPGMDMP) TOFILE(QTEMP/ERRORLST) +
JOB(&JOB_NUM/&USER/&JOB_NAME) +
SPLNBR(*LAST) MBROPT(*ADD)
CPYSPLF FILE(QPJOBLOG) TOFILE(QTEMP/ERRORLST) +
JOB(&JOB_NUM/&USER/&JOB_NAME) +
SPLNBR(*LAST) MBROPT(*ADD)
CRTFLR FLR(EMAIL)
MONMSG MSGID(CPF8A18)
CPYTOPCD FROMFILE(QTEMP/ERRORLST) TOFLR(EMAIL) +
TODOC(ERRORLST.TXT) REPLACE(*YES) +
TRNTBL(QTCPASC)
CHGVAR VAR(&OBJET) VALUE('Rapport détaillé de +
l''''erreur')
CHGDOCD DOC(ERRORLST.TXT) FLR(EMAIL) DOCD(&OBJET)
CHGVAR VAR(&MSG_ERR) VALUE('Cher service +
informatique, une erreur système a eu +
lieu sur le travail' *BCAT &JOB_NUM *TCAT +
'/' *TCAT &USER *TCAT '/' *TCAT &JOB_NAME +
*TCAT ', programme' *BCAT &PROGRAM *TCAT +
', instruction' *BCAT &ERROR *TCAT ', +
vous trouverez ci-joint le DUMP le +
rapport détaillé de l''''erreur et la log')
CHGVAR VAR(&EMET) VALUE(&PROGRAM *TCAT '@' *TCAT +
&SYSTEM *TCAT '.fr')
CHGVAR VAR(&SUJET) VALUE('ERREUR système')
CHGVAR VAR(&CMD) VALUE('SNDDST TYPE(*DOC) +
TOINTNET(' *TCAT &ADRMAIL *TCAT ') DSTD(''' +
*TCAT &OBJET *TCAT ''') DOC(erreur.log) +
FLR(EMAIL) LONGMSG(''' *TCAT &MSG_ERR *tcat ''')')
OVRPRTF FILE(QPQUPRFIL) DEVTYPE(*AFPDS)
CALL PGM(QCMDEXC) PARM(&CMD &LNG)
DLTF FILE(QTEMP/ERRORLST)
DLTDLO DLO(EMAIL)
FIN: ENDPGM
Figure 7
MAILINFO
Les adresses méls utilisées sont paramétrées dans la table MAILINFO.
R MAILINFOF
ID 10 0
REFERENCE 10
ADRMAIL 32
UNIQUE
R MAILINFOF PFILE(MAILINFO)
K ID
R MAILINFOF PFILE(MAILINFO)
K REFERENCE
Figure 8
Petite précaution, l’utilisateur qui génère l’erreur doit appartenir aux profils autorisés à envoyer des mails (WRKDIRE).
Un programme CLLE pour compiler tout ça peut s’avérer utile. Mettre la bibliothèque où sera utilisée cet outil en CURLIB.
PGM
/* Création de la fonction d'erreur non prévue */
CRTPF FILE(MAILINFO) SRCFILE(*CURLIB/QDDSSRC)
MONMSG MSGID(CPF0000)
CRTLF FILE(MAILINFOL1) SRCFILE(*CURLIB/QDDSSRC)
MONMSG MSGID(CPF0000)
CRTLF FILE(MAILINFOL2) SRCFILE(*CURLIB/QDDSSRC)
MONMSG MSGID(CPF0000)
CRTPRTF FILE(ERRORLST) SRCFILE(*CURLIB/QDDSSRC)
CRTDSPF FILE(FGESTERR) SRCFILE(*CURLIB/QDDSSRC)
CRTRPGMOD MODULE(QTEMP/GESTERR) +
SRCFILE(*CURLIB/QRPGLESRC) DBGVIEW(*ALL) +
OPTIMIZE(*FULL)
CRTCLMOD MODULE(QTEMP/MAILERR) +
SRCFILE(*CURLIB/QCLSRC) OPTIMIZE(*FULL) +
DBGVIEW(*ALL)
/* Création du programme de service */
CRTSRVPGM SRVPGM(SERVICE) MODULE(QTEMP/GESTERR +
QTEMP/MAILERR) SRCFILE(*CURLIB/QSRVSRC)
/* Création de la commande DSPFFDF */
CRTPF FILE(QTEMP/TEST) RCDLEN(500)
MONMSG MSGID(CPF0000)
DSPFFD FILE(QTEMP/TEST) OUTPUT(*OUTFILE) +
OUTFILE(QTEMP/DSPFFDF)
CRTCLMOD MODULE(QTEMP/DSPFFDF) +
SRCFILE(*CURLIB/QCLSRC) OPTIMIZE(*FULL) +
DBGVIEW(*ALL)
CRTPGM PGM(DSPFFDF) MODULE(QTEMP/DSPFFDF) +
BNDDIR(*CURLIB/OUTILS)
CRTCMD CMD(DSPFFDF) PGM(*CURLIB/DSPFFDF)
DSPFD FILE(QTEMP/TEST) TYPE(*ACCPTH) +
OUTPUT(*OUTFILE) OUTFILE(QTEMP/DSPKEYF)
CRTCLMOD MODULE(QTEMP/DSPKEYF) +
SRCFILE(*CURLIB/QCLSRC) OPTIMIZE(*FULL) +
DBGVIEW(*ALL)
CRTPGM PGM(DSPKEYF) MODULE(QTEMP/DSPKEYF) +
BNDDIR(*CURLIB/OUTILS)
CRTCMD CMD(DSPKEYF) PGM(*CURLIB/DSPKEYF)
DSPOBJD OBJ(QTEMP/*ALL) OBJTYPE(*ALL) +
OUTPUT(*OUTFILE) OUTFILE(QTEMP/DSPOBJDL)
CRTCLMOD MODULE(QTEMP/CHGOWNOBJL) +
SRCFILE(*CURLIB/QCLSRC) OPTIMIZE(*FULL) +
DBGVIEW(*ALL)
CRTPGM PGM(CHGOWNOBJL) MODULE(QTEMP/CHGOWNOBJL) +
BNDDIR(*CURLIB/OUTILS)
CRTCMD CMD(CHGOWNOBJL) PGM(*CURLIB/CHGOWNOBJL)
DSPOBJD OBJ(*CURLIB/*ALL) OBJTYPE(*QMQRY) OUTPUT(*OUTFILE) +
OUTFILE(QTEMP/DSPQMQRYD)
CRTCLMOD MODULE(QTEMP/RTVQMLIB) SRCFILE(*CURLIB/QCLSRC) OPTIMIZE(*FULL) +
DBGVIEW(*ALL)
CRTPGM PGM(RTVQMLIB) MODULE(QTEMP/RTVQMLIB) BNDDIR(*CURLIB/OUTILS)
CRTCMD CMD(RTVQMLIB) PGM(*CURLIB/RTVQMLIB)
ENDPGM
Figure 9