/* This is my program to read a file in reverse sequence in CL. */ /* something that, in my opinion, should never be done in CL. */ /* Scott Klement 9/10/2012 */ /* */ /* Warning: This is for "play" only. If you want a real solution */ /* please write it in an HLL like RPG, Cobol, C or C++ */ /* */ /* To compile: */ /*> CRTCLMOD MODULE(REVERSEF) SRCFILE(QCLSRC) DBGVIEW(*LIST) <*/ /*> CRTPGM PGM(REVERSEF) MODULE(REVERSEF) BNDDIR(QC2LE) <*/ /* */ /* To run: */ /* CALL PGM(REVERSEF) PARM('MYLIB/MYFILE') */ PGM PARM(&FILE) DCL VAR(&FILE) TYPE(*CHAR) LEN(32) DCL VAR(&FILEZ) TYPE(*CHAR) LEN(33) DCL VAR(&MODE) TYPE(*CHAR) LEN(33) DCL VAR(&NULL) TYPE(*CHAR) LEN(1) VALUE(x'00') DCL VAR(&HANDLE) TYPE(*PTR) DCL VAR(&NULLPTR) TYPE(*PTR) DCL VAR(&RRN) TYPE(*INT) LEN(4) DCL VAR(&RC) TYPE(*INT) LEN(4) DCL VAR(&FILEEND) TYPE(*INT) LEN(4) VALUE(33554436) DCL VAR(&NOLOCK) TYPE(*INT) LEN(4) VALUE(1) DCL VAR(&IOFBPTR) TYPE(*PTR) DCL VAR(&IOFB) TYPE(*CHAR) LEN(68) + STG(*BASED) BASPTR(&IOFBPTR) DCL VAR(&BYTES) TYPE(*INT) LEN(4) + STG(*DEFINED) DEFVAR(&IOFB 37) DCL VAR(&REC) TYPE(*CHAR) LEN(32767) DCL VAR(&RECSIZE) TYPE(*UINT) LEN(4) VALUE(32767) DCL VAR(&MSG) TYPE(*CHAR) LEN(70) CHGVAR VAR(&NULLPTR) VALUE(*NULL) /* This API opens the file in read-only mode (rr) + and in RRN sequence (arrseq=Y)' */ CHGVAR VAR(&FILEZ) VALUE(&FILE *TCAT &NULL) CHGVAR VAR(&MODE) VALUE('rr, arrseq=Y' *TCAT &NULL) CALLPRC PRC('_Ropen') PARM((&FILEZ *BYREF) + (&MODE *BYREF)) + RTNVAL(&HANDLE) /* _Rlocate positions the file. In this case, I'm + specifying &FILEEND to move to the end of the file + The key and rrn fields are ignored with FILEEND */ CALLPRC PRC('_Rlocate') PARM((&HANDLE *BYVAL) + (&NULLPTR *BYVAL) + (&RRN *BYVAL) + (&FILEEND *BYVAL)) + RTNVAL(&IOFBPTR) /* _Rreadp API reads the previous record in the file. + since this is a read-only process, I'm specifying + NOLOCK so that the record cannot be locked. */ CALLPRC PRC('_Rreadp') PARM((&HANDLE *BYVAL) + (&REC *BYREF) + (&RECSIZE *BYVAL) + (&NOLOCK *BYVAL)) + RTNVAL(&IOFBPTR) /* As long as the _Rreadp API keeps returning bytes + read (in the &BYTES var, populated via the &IOFBPTR + variable) I'll keep reading mode from the file. */ DOWHILE (&BYTES *GT 0) CHGVAR VAR(&MSG) VALUE(%SST(&REC 1 &BYTES)) SNDUSRMSG MSG(&MSG) MSGTYPE(*INFO) TOMSGQ(*EXT) CHGVAR VAR(&REC) VALUE(' ') CALLPRC PRC('_Rreadp') PARM((&HANDLE *BYVAL) + (&REC *BYREF) + (&RECSIZE *BYVAL) + (&NOLOCK *BYVAL)) + RTNVAL(&IOFBPTR) ENDDO /* Finally, close the file */ CALLPRC PRC('_Rclose') PARM((&HANDLE *BYVAL)) RTNVAL(&RC) RETURN ENDPGM