EXCCMDMBR: PGM PARM(&PMBR &PQF &PERROPT) DCL VAR(&PMBR) TYPE(*CHAR) LEN(10) DCL VAR(&PQF) TYPE(*CHAR) LEN(20) DCL VAR(&PERROPT) TYPE(*CHAR) LEN(10) DCL VAR(&MBR) TYPE(*CHAR) LEN(10) DCL VAR(&F) TYPE(*CHAR) LEN(10) DCL VAR(&FLIB) TYPE(*CHAR) LEN(10) DCL VAR(&ERROPT) TYPE(*CHAR) LEN(10) DCL VAR(&OPTCTLBLK) TYPE(*CHAR) LEN(20) + VALUE('*DFT') DCL VAR(&MULTI) TYPE(*LGL) VALUE('0') DCL VAR(&CONT) TYPE(*LGL) VALUE('0') DCL VAR(&PLUS) TYPE(*LGL) VALUE('0') DCL VAR(&MINUS) TYPE(*LGL) VALUE('0') DCL VAR(&CMD) TYPE(*CHAR) LEN(3000) DCL VAR(&RECLEN) TYPE(*DEC) LEN(5) DCL VAR(&RECEND) TYPE(*DEC) LEN(5) DCL VAR(&CMDLEN) TYPE(*DEC) LEN(5) DCL VAR(&RECPOS) TYPE(*DEC) LEN(5) DCL VAR(&CMDPOS) TYPE(*DEC) LEN(5) DCLF FILE(QGPL/QCLSRC) /*---------------------------------------------------------------------------*/ /* Global MONMSG... */ /*---------------------------------------------------------------------------*/ MONMSG MSGID(CPF0000 MCH0000) EXEC(GOTO + CMDLBL(STDERR)) /* */ /* Extract working values from parms... */ /* */ CHGVAR VAR(&MBR) VALUE(&PMBR) CHGVAR VAR(&F) VALUE(%SST(&PQF 1 10)) CHGVAR VAR(&FLIB) VALUE(%SST(&PQF 11 10)) CHGVAR VAR(&ERROPT) VALUE(&PERROPT) /* */ /* Verify that referenced file/mbr exist... */ /* */ CHKOBJ OBJ(&FLIB/&F) OBJTYPE(*FILE) CHKOBJ OBJ(&FLIB/&F) OBJTYPE(*FILE) MBR(&MBR) /* */ /* Set options control block if the *CHECK option is requested... */ /* */ IF COND(&ERROPT *EQ '*CHECK') THEN(DO) CHGVAR VAR(&OPTCTLBLK) VALUE('*CHECK') ENDDO /* Point to our CL member... */ OVRDBF FILE(QCLSRC) TOFILE(&FLIB/&F) MBR(&MBR) /* */ /* At the beginning of each command, we clear the command buffer and */ /* reposition to the beginning of the buffer... */ /* */ /* A CL member can contain many commands. Each command may span many */ /* records. We have two loops (nested) for records within commands... */ /* */ /*----------------------- Command loop ------------------------------*/ NXT_CMD: CHGVAR VAR(&CMDPOS) VALUE(1) CHGVAR VAR(&CMD) VALUE(' ') /*---------------------- Record loop ------------------------*/ NXT_REC: RCVF MONMSG MSGID(CPF0864) EXEC(GOTO CMDLBL(END_REC)) /* */ /* Blank lines are simply skipped... */ /* */ IF COND(&SRCDTA *EQ ' ') THEN(GOTO + CMDLBL(NXT_REC)) /* */ /* Find the last non-blank in the source record data field... */ /* */ RTNLEN VALUE(&SRCDTA) LEN(&RECEND) /* */ /* Default to the first position of the source data field... */ /* */ CHGVAR VAR(&RECPOS) VALUE(1) /* */ /* We check to see if the &MULTI indicator is on from the previous source */ /* record. If it is, that means the current record is a continuation... */ /* */ IF COND(&MULTI) THEN(DO) /* */ /* A continuation can be either &PLUS or &MINUS. If it's &PLUS, we need to */ /* locate the first non-blank character. For &MINUS, we remain */ /* positioned at the beginning because leading blanks are included. */ /* */ IF COND(&PLUS) THEN(DO) /* Loop until non-blank... */ NXT_SPC: IF COND(%SST(&SRCDTA &RECPOS 1) *EQ ' ') THEN(DO) CHGVAR VAR(&RECPOS) VALUE(&RECPOS +1) GOTO CMDLBL(NXT_SPC) ENDDO /* NXT_SPC... */ ENDDO /* &PLUS... */ ENDDO /* */ /* Now that we've set everything based on indicators from the previous */ /* record, we can set the indicators for the current record... */ /* */ IF COND(%SST(&SRCDTA &RECEND 1) *EQ '+') THEN(DO) CHGVAR VAR(&MULTI) VALUE('1') CHGVAR VAR(&PLUS) VALUE('1') CHGVAR VAR(&MINUS) VALUE('0') ENDDO ELSE CMD(DO) IF COND(%SST(&SRCDTA &RECEND 1) *EQ '-') THEN(DO) CHGVAR VAR(&MULTI) VALUE('1') CHGVAR VAR(&PLUS) VALUE('0') CHGVAR VAR(&MINUS) VALUE('1') ENDDO ELSE CMD(DO) CHGVAR VAR(&MULTI) VALUE('0') CHGVAR VAR(&PLUS) VALUE('0') CHGVAR VAR(&MINUS) VALUE('0') ENDDO ENDDO /* */ /* If the current record is &MULTI, we need to set the length by reducing */ /* the length by one. This strips off the PLUS or MINUS character... */ /* */ IF COND(&MULTI) THEN(DO) CHGVAR VAR(&RECLEN) VALUE(&RECEND - &RECPOS) ENDDO ELSE CMD(DO) /* &MULTI... */ CHGVAR VAR(&RECLEN) VALUE(&RECEND - &RECPOS + 1) ENDDO /* */ /* We have all our lengths and positions set; now move the significant */ /* part of the current source data field into the command buffer... */ /* */ CHGVAR VAR(%SST(&CMD &CMDPOS &RECLEN)) + VALUE(%SST(&SRCDTA &RECPOS &RECLEN)) /* */ /* Move our pointer down the command buffer according to the length we */ /* moved into it... */ /* */ CHGVAR VAR(&CMDPOS) VALUE(&CMDPOS + &RECLEN) /* */ /* If the current record is &MULTI, go back to get the continuation */ /* that should follow... */ /* */ IF COND(&MULTI) THEN(GOTO CMDLBL(NXT_REC)) /*---------------------- Record loop ------------------------*/ /* */ /* ...otherwise... */ /* */ /* Get the final length of the command buffer to pass to the command */ /* execution API... */ /* */ RTNLEN VALUE(&CMD) LEN(&CMDLEN) /* */ /* ...and execute that command. */ /* */ PRCCMD CMD(&CMD) CMDLEN(&CMDLEN) OCB(&OPTCTLBLK) MONMSG MSGID(CPF0000 MCH0000) EXEC(DO) IF COND(&ERROPT *EQ '*ABORT' *OR &ERROPT *EQ + '*CHECK') THEN(DO) GOTO CMDLBL(STDERR) ENDDO ENDDO /* MONMSG... */ /* */ /* Now go back to see if there are any more... */ /* */ GOTO CMDLBL(NXT_CMD) /*----------------------- Command loop ------------------------------*/ END_REC: RETURN STDERR: MOVDIAGMSG MONMSG MSGID(CPF0000 MCH0000) RSNESCMSG MONMSG MSGID(CPF0000 MCH0000) ENDPGM