CL Programs with Subroutines
CL can use subroutines much like RPG.
Creating subroutines in a CLP
The Subroutine (SUBR) command may be used in a CL program or procedure, along with the End Subroutine (ENDSUBR) command, to encapsulate a group of commands that are specific to that subroutine. The name of the subroutine, used by the CALLSUBR command, is identified by the SUBR parameter on the SUBR command.
/*********************************************************************/ /* Program Name -CSG200CL */ /* */ /* Function - This program was designed to read a directory and */ /* decrypt inbound files. */ /* */ /* */ /* Programmer - Steve Croy 99/99/9999 */ /*********************************************************************/ PGM DCLPRCOPT DFTACTGRP(*NO) ACTGRP(CSGRCV) + BNDSRVPGM((ISI000SV)) DCL VAR(&IMPFOLDER) TYPE(*CHAR) LEN(200) DCL VAR(&DIRECTORY) TYPE(*CHAR) LEN(200) DCL VAR(&ARCFOLDER) TYPE(*CHAR) LEN(200) DCL VAR(&ERRFOLDER) TYPE(*CHAR) LEN(200) DCL VAR(&MSGKEY) TYPE(*CHAR) LEN(4) DCL VAR(&PGMNAME) TYPE(*CHAR) LEN(10) DCL VAR(&FUNCTION) TYPE(*CHAR) LEN(25) DCL VAR(&PROGRAM) TYPE(*CHAR) LEN(15) DCL VAR(&SENDER) TYPE(*CHAR) LEN(80) DCL VAR(&FILEPATH) TYPE(*CHAR) LEN(200) DCL VAR(&newPath) TYPE(*CHAR) LEN(200) DCL VAR(&JOBTYPE) TYPE(*CHAR) LEN(1) DCL VAR(&FILETYPE) TYPE(*CHAR) LEN(1) DCL VAR(&PHRASE) TYPE(*CHAR) LEN(200) DCL VAR(&CSGFTP) TYPE(*CHAR) LEN(15) + VALUE('CSGFTP') DCL VAR(&SYSNAME) TYPE(*CHAR) LEN(8) DCL VAR(&POS) TYPE(*UINT) LEN(2) DCL VAR(&QT) TYPE(*CHAR) LEN(1) VALUE('''') DCL VAR(&G) TYPE(*UINT) LEN(2) DCL VAR(&Z7CMD) TYPE(*CHAR) LEN(255) DCL VAR(&SUBJECT) TYPE(*CHAR) LEN(50) dcl var(&message) type(*char) len(80) dcl var(&reason) type(*char) len(80) dcl var(&error) type(*lgl) len(1) dcl var(&error) type(*lgl) len(1) RTVJOBA TYPE(&JOBTYPE) RTVNETA SYSNAME(&SYSNAME) /*-------------------------------------------------------------------*/ /* Get the program name */ /*-------------------------------------------------------------------*/ SNDPGMMSG MSG(' ') TOPGMQ(*SAME) MSGTYPE(*INFO) + KEYVAR(&MSGKEY) RCVMSG PGMQ(*SAME) MSGTYPE(*INFO) RMV(*YES) + SENDER(&SENDER) CHGVAR VAR(&PGMNAME) VALUE(%SST(&SENDER 56 10)) CHGVAR VAR(&PROGRAM) VALUE(&PGMNAME) /*-------------------------------------------------------------------*/ /* Add FTP manager library to the library list. */ /* Use SFTP to get the inbound data from CSG. */ /*-------------------------------------------------------------------*/ IF COND(&SYSNAME *EQ 'TEST400') THEN(GOTO + CMDLBL(GETNAME)) ADDLIBLE LIB(ALLFTM100) MONMSG MSGID(CPF0000) FTMSFTPEXC FTPDFN(CSGINBOUND) LCLFIL(' ') RMTFIL(' ') /*-------------------------------------------------------------------*/ /* Get the folder where the CSG data is to be Archived */ /*-------------------------------------------------------------------*/ GETNAME: ADDLIBLE LIB(ALLFTM100) MONMSG MSGID(CPF0000) CHGVAR VAR(&FUNCTION) VALUE('IMPFOLDER') CALL PGM(ISI005RP) PARM(&PROGRAM &FUNCTION &IMPFOLDER) CHGVAR VAR(&DIRECTORY) VALUE(&IMPFOLDER) CHGVAR VAR(&FUNCTION) VALUE('ARCFOLDER') CALL PGM(ISI005RP) PARM(&PROGRAM &FUNCTION &ARCFOLDER) CHGVAR VAR(&FUNCTION) VALUE('ERRFOLDER') CALL PGM(ISI005RP) PARM(&PROGRAM &FUNCTION + &ERRFOLDER) /* sac04 */ CHGVAR VAR(&FUNCTION) VALUE('PHRASE') CALL PGM(ISI005RP) PARM(&CSGFTP &FUNCTION &PHRASE) /*-------------------------------------------------------------------*/ /* Read the files in the folder and move them to archive */ /*-------------------------------------------------------------------*/ LIST: CALL PGM(ISI010RP) PARM(&IMPFOLDER) READ: DOUNTIL COND(&FILEPATH *EQ '*****') CALL PGM(ISI020RP) PARM(&FILEPATH) IF COND(&FILEPATH *NE '*****') THEN(DO) /*-------------------------------------------------------------------*/ /* Check the file name to determine if the file needs decrypting. */ /*-------------------------------------------------------------------*/ CHGVAR VAR(&FILETYPE) VALUE(' ') JOBFILE: IF COND(%SCAN('.job' &FILEPATH) *NE 0 *OR + %SCAN('.JOB' &FILEPATH) *NE 0) + THEN(CHGVAR VAR(&FILETYPE) VALUE('J')) IF COND(&FILETYPE *EQ 'J') THEN(GOTO + CMDLBL(CALLS)) Decrypt: IF COND(%SCAN('.pgp' &FILEPATH) *NE 0 *OR + %SCAN('.PGP' &FILEPATH) *NE 0) + THEN(CHGVAR VAR(&FILETYPE) VALUE('P')) IF COND(&FILETYPE *EQ 'P') THEN(GOTO + CMDLBL(CALLS)) UNZIP: IF COND(%SCAN('.zip' &FILEPATH) *NE 0 *OR + %SCAN('.ZIP' &FILEPATH) *NE 0) + THEN(CHGVAR VAR(&FILETYPE) VALUE('Z')) gzZIP: IF COND(%SCAN('.gz' &FILEPATH) *NE 0 *OR + %SCAN('.GZ' &FILEPATH) *NE 0) + THEN(CHGVAR VAR(&FILETYPE) VALUE('G')) CALLS: SELECT WHEN COND(&FILETYPE *EQ 'P') THEN(CALLSUBR + SUBR(DECRYPTED)) /* 'PGP Encrypted' */ WHEN COND(&FILETYPE *EQ 'Z') THEN(CALLSUBR + SUBR(UNZIPPED)) /* 'Zipped file' */ WHEN COND(&FILETYPE *EQ 'G') THEN(CALLSUBR + SUBR(GUNZIP)) /* ' GZipped file' */ WHEN COND(&FILETYPE *EQ 'J') THEN(CALLSUBR + SUBR(LOGJOB)) /* 'Job file' */ ENDSELECT ENDIF: ENDDO ENDLOOP: ENDDO CHGVAR VAR(&DIRECTORY) VALUE(&DIRECTORY *TCAT '*.*') CHGAUT OBJ(&DIRECTORY) USER(*PUBLIC) DTAAUT(*RWX) + OBJAUT(*ALL) SBMJOB CMD(CALL PGM(CSG205CL)) JOB(MOVCSGDTA) + JOBQ(CYCJOBQ) TERMINATE: RETURN /*-----------------------------------------------------------------*/ PGPPROC: SUBR SUBR(DECRYPTED) PGPDECRYPT IFSFILE(&FILEPATH) PASSWORD(&PHRASE) + BATCH(*YES) PGPVER(*PGPCL9) /* SAC02 */ CALLSUBR SUBR(ARCHIVED) CHGVAR VAR(&POS) VALUE(%SCAN('.pgp' &FILEPATH)) IF COND(&POS *EQ 0) THEN(CHGVAR VAR(&POS) + VALUE(%SCAN('.PGP' &FILEPATH))) IF COND(&POS *GT 0) THEN(CHGVAR + VAR(%SST(&FILEPATH &POS 4)) VALUE(' ')) IF COND(%SCAN('.zip' &FILEPATH) *GT 0 *OR + %SCAN('.ZIP' &FILEPATH) *GT 0) + THEN(CALLSUBR SUBR(UNZIPPED)) IF COND(%SCAN('.gz' &FILEPATH) *GT 0 *OR + %SCAN('.GZ' &FILEPATH) *GT 0) + THEN(CALLSUBR SUBR(GUNZIP)) ENDSUBR /*-----------------------------------------------------------------*/ /* Bypass return files -- required for testing period, not */ /* for production. */ /*-----------------------------------------------------------------*/ ZIPPROC: SUBR SUBR(UNZIPPED) IF COND(%SCAN('PSS' &FILEPATH) *GT 0 *OR + %SCAN('PSS' &FILEPATH) *GT 0) THEN(GOTO + CMDLBL(NOUNZIP)) CHGVAR VAR(&POS) VALUE(%SCAN('.zip' &FILEPATH)) IF COND(&POS *EQ 0) THEN(CHGVAR VAR(&POS) + VALUE(%SCAN('.ZIP' &FILEPATH))) IF COND(&POS *GT 0) THEN(UNZIPF + ARCHIVE(&FILEPATH) DIR(&IMPFOLDER)) CALLSUBR SUBR(ARCHIVED) NOUNZIP: ENDSUBR /*-----------------------------------------------------------------*/ GZIPPROC: SUBR SUBR(GUNZIP) ADDENVVAR ENVVAR(QIBM_QSH_CMD_ESCAPE_MSG) VALUE(Y) MONMSG MSGID(CPFA980) CHGVAR VAR(&Z7CMD) VALUE(' ') CHGVAR VAR(&Z7CMD) VALUE('7z x' *BCAT &FILEPATH) CHGVAR VAR(&Z7CMD) VALUE(&Z7CMD *TCAT ' -o' *TCAT + &IMPFOLDER) STRQSH CMD(&Z7CMD) MONMSG MSGID(QSH0005) CALLSUBR SUBR(ARCHIVED) ENDSUBR /*-----------------------------------------------------------------*/ JOBPROC: SUBR SUBR(LOGJOB) CALL PGM(CSG201RP) PARM(&FILEPATH &NEWPATH) CALLSUBR SUBR(ARCHIVED) ENDSUBR /*-----------------------------------------------------------------*/ ARCFILE: SUBR SUBR(ARCHIVED) MOV OBJ(&FILEPATH) TODIR(&ARCFOLDER) MONMSG MSGID(CPFA0A0) EXEC(DO) CALLSUBR SUBR(ARCHIVESR) ENDDO ENDSUBR /*==================================================================*/ /* move file to archive */ /*==================================================================*/ SUBR SUBR(ARCHIVESR) CHGVAR VAR(&message) VALUE(' ') CHGVAR VAR(&SUBJECT) VALUE(' ') CHGVAR VAR(&reason) VALUE(' ') RETRY: CHGVAR VAR(&ERROR) VALUE('0') MOV OBJ(&FILEPATH) TODIR(&ARCFOLDER) MONMSG MSGID(CPFA0A0) EXEC(DO) CHGVAR VAR(&ERROR) VALUE('1') CALL PGM(CSG305RP) PARM(&FILEPATH &ARCFOLDER) ENDDO IF COND(&ERROR) THEN(GOTO CMDLBL(RETRY)) CHGVAR VAR(&SUBJECT) VALUE('CSG200CL file + error') CHGVAR VAR(&MESSAGE) VALUE('Error occurred on + move to archive inbound file.') CHGVAR VAR(&REASON) VALUE('Check the job log of + CSGINBOUND for details.') CALL PGM(CSG415CL) PARM(&SUBJECT &MESSAGE &REASON) ENDSUBR ENDPGM
The first SUBR command that is encountered in a program or procedure also marks the end of the mainline of that program
or procedure. All commands from this point forward, with the exception of the ENDPGM command, must
be contained within a subroutine, in other words, placed between a beginning (SUBR) and ending (ENDSUBR) commands. The SUBR
and ENDSUBR commands must be matched pairs, and may not be nested. A subroutine may contain only one SUBR and ENDSUBR command.
using a SUBR between the beginning and end of the subroutine is not permitted.