|
Hello Kirwin, Well, I'd think that questions not specific to a particular list go in the general bucket and therefore belong on the MIDRANGE-L list. David may want to consider a CL list but I don't think that is necessary. Now to your specific problem: There are two rules to understand about CL and file processing. 1/ You can only process one file per CL program 2/ Once EOF is reached you cannot process that file any further. You cannot break these rules at all but you can work around them The most common technique to defeat rule 1 is to use multiple CL programs -- 1 program per file. So for instance, if you need to process a list of files and for each file process a list of fields, you would need one CL program to process a list of files created using the DSPOBJD or DSPFD commands and a second CL program to process a list of fields created using the DSPFFD command (or you could stop messing around with CL and process both files in a HLL). But you can use a little-known trick of transferring control to yourself which effectively ends the invocation and allows you to reprocess the file. Rule 2 is harder to break because the code behind a CL program sets a flag when EOF is reached and it really doesn't matter what you do after that. Any I/O to the file will result in EOF. CLOF and OPNDBF doesn't help. POSDBF doesn't help either. The EOF flag is not reset until the CL program ends. One solution is to count the number of records processed and never reach EOF. Then you can use POSDBF to reposition. The code looks something like this -- using your code as a starting point: DCLF FILE(QSYS/QADSPOBJ) DSPOBJD OBJ(LIB1/*ALL) OBJTYPE(*FILE) + OUTPUT(*OUTFILE) OUTFILE(QTEMP/FILE) + OUTMBR(*FIRST *REPLACE) OVRDBF FILE(QADSPOBJ) TOFILE(QTEMP/FILE) RTVMBRD FILE(QTEMP/FILE) MBR(*FIRST) + NBRCURRCD(&RCDCOUNT) CHGVAR &LOOPCOUNT 0 LOOP1: IF (&RCDCOUNT *LT &LOOPCOUNT) THEN(DO) RCVF DEV(*FILE) RCDFMT(*FILE) WAIT(*YES) /* Code... */ CHGVAR &LOOPCOUNT (&LOOPCOUNT + 1) GOTO CMDLBL(LOOP1) ENDDO EOF1: DSPOBJD OBJ(LIB2/*ALL) OBJTYPE(*FILE) + OUTPUT(*OUTFILE) OUTFILE(QTEMP/FILE) + OUTMBR(*FIRST *REPLACE) RTVMBRD FILE(QTEMP/FILE) MBR(*FIRST) + NBRCURRCD(&RCDCOUNT) POSDBF OPNID(FILE) POSITION(*START) CHGVAR &LOOPCOUNT 0 LOOP2: IF (&RCDCOUNT *LT &LOOPCOUNT) THEN(DO) RCVF DEV(*FILE) RCDFMT(*FILE) WAIT(*YES) /* Code... */ CHGVAR &LOOPCOUNT (&LOOPCOUNT + 1) GOTO CMDLBL(LOOP2) ENDDO EOF2: LOOP3 RCVF MONMSG MSGID(CPF0864) EXEC(DO) RCVMSG MSGTYPE(*EXCP) /* Cleanup joblog */ DLTF FILE(QTEMP/FILE) RCVMSG MSGTYPE(*LAST) /* Cleanup joblog */ GOTO CMDLBL(EXIT) ENDDO GOTO CMDLBL(LOOP3) EXIT: RETURN Also pay attention to the DCLF and OVRDBF statements which are the proper way to handle IBM outfiles. And also the code to cleanup the joblog -- we don't all have to write CL like HelpSystems. There is no need to delete the file just to replace it -- that's what the OUTMBR keyword is for. The LOOP3 code is to ensure that EOF is reached otherwise the DLTF will fail with an in-use message. A second solution is build the outfile with all the records before processing and test the library name to condition processing. That looks something like: DCLF FILE(QSYS/QADSPOBJ) DSPOBJD OBJ(LIB1/*ALL) OBJTYPE(*FILE) + OUTPUT(*OUTFILE) OUTFILE(QTEMP/FILE) + OUTMBR(*FIRST *REPLACE) DSPOBJD OBJ(LIB2/*ALL) BJTYPE(*FILE) + OUTPUT(*OUTFILE) OUTFILE(QTEMP/FILE) + OUTMBR(*FIRST *ADD) /* <=================== */ OVRDBF FILE(QADSPOBJ) TOFILE(QTEMP/FILE) LOOP1: RCVF DEV(*FILE) RCDFMT(*FILE) WAIT(*YES) MONMSG MSGID(CPF0864) EXEC(DO) RCVMSG MSGTYPE(*EXCP) /* Cleanup joblog */ GOTO CMDLBL(EOF1) ENDDO IF (&ODLBNM *EQ 'LIB1') THEN(DO) /* Code... */ ELSE DO /* Code... */ ENDDO GOTO CMDLBL(LOOP1) EOF1: DLTF FILE(QTEMP/FILE) A third solution is to transfer control to the same CL program effectively calling yourself but without increasing the invocation stack. Pass a counter variable in as a parameter with an initial value of zero. PGM PARM(&COUNTER) DCL VAR(&COUNTER) TYPE(*DEC) LEN(5 0) DCLF FILE(QSYS/QADSPOBJ) IF (&COUNTER *EQ 0) THEN(DO) CHGVAR &LIB 'LIB1' ENDDO ELSE IF (&COUNTER *EQ 1) THEN(DO) CHGVAR &LIB 'LIB2' ENDDO ELSE IF (&COUNTER *EQ 2) THEN(RETURN) DSPOBJD OBJ(&LIB/*ALL) OBJTYPE(*FILE) + OUTPUT(*OUTFILE) OUTFILE(QTEMP/FILE) + OUTMBR(*FIRST *REPLACE) OVRDBF FILE(QADSPOBJ) TOFILE(QTEMP/FILE) LOOP1: RCVF DEV(*FILE) RCDFMT(*FILE) WAIT(*YES) MONMSG MSGID(CPF0864) EXEC(DO) RCVMSG MSGTYPE(*EXCP) /* Cleanup joblog */ GOTO CMDLBL(EOF1) ENDDO /* Code... */ GOTO CMDLBL(LOOP1) EOF1: CHGVAR &COUNTER (&COUNTER + 1) TFRCTL PGM(THISPGM) PARM(&COUNTER) I have used this technique to accept a list as a parameter and iteratively process the list by TFRCTL for each item in the list. It is especially useful when the information about the item comes from an outfile. Regards, Simon Coulter. «»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«» «» FlyByNight Software AS/400 Technical Specialists «» «» Eclipse the competition - run your business on an IBM AS/400. «» «» «» «» Phone: +61 3 9419 0175 Mobile: +61 0411 091 400 «» «» Fax: +61 3 9419 0175 mailto: shc@flybynight.com.au «» «» «» «» Windoze should not be open at Warp speed. «» «»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»
Date: Thu, 30 Dec 1999 14:31:13 -0600 From: "Kerwin Crawford" <crawfork@toastmaster.com> To: RPG400-L@midrange.com Reply-To: RPG400-L@midrange.com Subject: Another CL Question - RCVF
know this is a RPG list but I don't know of a CLP list. I have a CLP that is basically the following. The main process is to read all of the files in a library do some things with it and then read all of the files from a related library and do some things. See example: DCLF FILE(QTEMP/FILE) DSPOBJD OBJ(LIB1/*ALL) OBJTYPE(*FILE) + OUTPUT(*OUTFILE) OUTFILE(QTEMP/FILE) + OUTMBR(*FIRST *REPLACE) LOOP1: RCVF DEV(*FILE) RCDFMT(*FILE) WAIT(*YES) MONMSG MSGID(CPF0864) EXEC(GOTO CMDLBL(EOF1)) /* Code... */ GOTO CMDLBL(LOOP1) EOF1: DLTF FILE(QTEMP/FILE) DSPOBJD OBJ(LIB2/*ALL) OBJTYPE(*FILE) + OUTPUT(*OUTFILE) OUTFILE(QTEMP/FILE) + OUTMBR(*FIRST *REPLACE) LOOP2: RCVF DEV(*FILE) RCDFMT(*FILE) WAIT(*YES) MONMSG MSGID(CPF0864) EXEC(GOTO CMDLBL(EOF2)) /* Code... */ GOTO CMDLBL(LOOP2) EOF2: DLTF FILE(QTEMP/FILE) My problem is that when it gets to the second rcvf it acts as if it has hit the EOF before processing the first record. I have tried putting in ovrdbf in several ways, but never got it to work. There has to be a way to reset the pointer or message to allow for the second rcvf. I ended up splitting this up into two CLP's and doing it that way. Any thoughts? Kerwin S. Crawford Toastmaster Inc. System Analyst
I know this is a RPG list but I
don't know of a CLP list.
I have a CLP that is basically the
following. The main process is to read all of the files in a library do
some things with it and then read all of the files from a related library and do
some things. See example:
DCLF FILE(QTEMP/FILE)
DSPOBJD OBJ(LIB1/*ALL) OBJTYPE(*FILE)
+
OUTPUT(*OUTFILE) OUTFILE(QTEMP/FILE) + OUTMBR(*FIRST *REPLACE) LOOP1:
RCVF DEV(*FILE) RCDFMT(*FILE)
WAIT(*YES)
MONMSG MSGID(CPF0864) EXEC(GOTO CMDLBL(EOF1)) /*
Code... */
GOTO CMDLBL(LOOP1)
EOF1:
DLTF FILE(QTEMP/FILE)
DSPOBJD OBJ(LIB2/*ALL) OBJTYPE(*FILE)
+
OUTPUT(*OUTFILE) OUTFILE(QTEMP/FILE) + OUTMBR(*FIRST *REPLACE) LOOP2:
RCVF DEV(*FILE) RCDFMT(*FILE)
WAIT(*YES)
MONMSG MSGID(CPF0864) EXEC(GOTO CMDLBL(EOF2)) /*
Code... */
GOTO CMDLBL(LOOP2)
EOF2:
DLTF FILE(QTEMP/FILE) My problem is that when it gets to
the second rcvf it acts as if it has hit the EOF before processing the first
record. I have tried putting in ovrdbf in several ways, but never got it
to work. There has to be a way to reset the pointer or message to allow
for the second rcvf.
I ended up splitting this up into two CLP's and
doing it that way.
Any thoughts?
Kerwin S. Crawford Toastmaster Inc. System Analyst |
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2025 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.