The addition of Perl and Java as AS/400 languages has introduced a new option of how and where these source programs may be stored. Perl has the flexibility of being stored either in a source physical file or in a stream file in the Integrated File System (IFS), while Java requires the program be stored in ASCII as a stream file in the IFS. Of course, there are many personal computer-based editors you can use to manipulate stream files in the IFS, but I thought it would be nice to have an option to edit these files using a tool we are all familiar with-SEU.
The first obstacle to overcome is that SEU cannot directly edit a stream file. Some intermediate conversion must take place first. OS/400 has a number of commands available for working with directories and files in the IFS, but no native stream file editor. So, I came up with a command I call Edit Stream Member (EDTSTMMBR). EDTSTMMBR uses IFS commands such as Copy From Stream File (CPYFRMSTMF) and Copy To Stream File (CPYTOSTMF) to perform the required intermediate conversions. See Figure 2 for the EDTSTMMBR command definition source code and Figure 3 for the CPP (STM001CL) source code.
Here is how EDTSTMMBR works. First, a temporary source file (@ED) is created in QTEMP. One member (SOURCE) is added to hold the converted program source, and a second member (@NULL) is added and used later to create, if necessary, a new stream file in the IFS.
Second, the single parameter passed to the program (&PATH) is scanned to determine if it contains any slashes (/), indicating a fully qualified path to the stream file we want to edit. If the supplied path does not contain a slash, we assume only the name of the stream file was supplied. In that case, EDTSTMMBR then retrieves the current directory in the IFS, using the Retrieve Current Directory (RTVCURDIR) command, and appends the file name to that directory. By the way, your default directory should be /home/USERNAME (where USERNAME is your user profile). You can change your default home directory at any time by using the Change User Profile (CHGUSRPRF) command.
Third, we copy the stream file (now referenced by the variable &FULLPATH) to the file
QTEMP/@ED, member SOURCE. If it is a new file (doesn't exist in the IFS), we also create the file in the IFS by copying the @NULL member in QTEMP/@ED, using the CPYTOSTMF. At this point, we can now edit the converted stream file, using STRSEU.
After we have finished editing the file, a simple test is made to determine if any records exist in the temporary source file member. If &NUMRECS is greater than zero, we replace the stream file using the CPYTOSTMF command. If &NUMRECS is zero, we just delete the file.
There are a couple of things to remember when using this command: You will not be able to use the Browse/Copy Options in SEU to copy source from another stream file, and any stream file records longer than 228 bytes will be truncated. These limitations aside, you will still be able to use old, reliable SEU for all your program editing needs.
- David Wilson
Strategic Fulfillment Group
Email:
Figure 2: Command EDTSTMMBR
/*===================================================================*/
/* To compile: */
/* */
/* CRTCMD CMD(XXX/EDTSTMMBR) PGM(XXX/STM001CL) + */
/* SRCFILE(XXX/QCMDSRC) TEXT('Edit Stream + */
/* File Member') ALLOW(*IPGM *IMOD *INTERACT +*/
/* *EXEC) */
/* */
/*===================================================================*/
CMD PROMPT('Edit Stream File Member')
PARM KWD(PATH) TYPE(*PNAME) LEN(512) MIN(1) +
EXPR(*YES) PROMPT('Path') /*===================================================================*/
/* To compile: */
/* */
/* CRTCLPGM PGM(XXX/STM001CL) SRCFILE(XXX/QCLSRC) + */
/* TEXT('CPP for EDTSTMMBR command') */
/* */
/*===================================================================*/
PGM PARM(&PATH)
DCL VAR(&CURDIR) TYPE(*CHAR) LEN(512)
DCL VAR(&DIRLEN) TYPE(*DEC) LEN(7)
DCL VAR(&FULLPATH) TYPE(*CHAR) LEN(1024)
DCL VAR(&NBRRECS) TYPE(*DEC) LEN(10) VALUE(0)
DCL VAR(&PATH) TYPE(*CHAR) LEN(512)
DCL VAR(&PATLEN) TYPE(*DEC) LEN(3) VALUE(1)
DCL VAR(&PATLOC) TYPE(*DEC) LEN(3) VALUE(0)
DCL VAR(&PATHLEN) TYPE(*DEC) LEN(3) VALUE(512)
DCL VAR(&STRLEN) TYPE(*DEC) LEN(3) VALUE(12)
DCL VAR(&STRPOS) TYPE(*DEC) LEN(3) VALUE(1)
DCL VAR(&SYSLVL) TYPE(*CHAR) LEN(9)
MONMSG MSGID(CPF0000 MCH0000) EXEC(GOTO CMDLBL(ERROR))
/* Ensure system is at V3 or later */
RTVOBJD OBJ(QSYS/QCMD) OBJTYPE(*PGM) SYSLVL(&SYSLVL)
IF COND(%SST(&SYSLVL 1 3) *LT 'V03') THEN(DO)
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) +
MSGDTA('EDTSTMMBR command requires at +
Figure 3: CL Program STM001CL
least OS/400 version 3.05') MSGTYPE(*ESCAPE)
ENDDO
/* Create a working source file in QTEMP for editing */
CHKOBJ OBJ(QTEMP/@ED) OBJTYPE(*FILE)
MONMSG MSGID(CPF9801) EXEC(DO)
CRTSRCPF FILE(QTEMP/@ED) RCDLEN(228) TEXT('Stream file +
working source')
ADDPFM FILE(QTEMP/@ED) MBR(@NULL) TEXT('Null member +
for file create')
INZPFM FILE(QTEMP/@ED) MBR(@NULL) TOTRCDS(1)
ADDPFM FILE(QTEMP/@ED) MBR(SOURCE) TEXT(' ') +
SRCTYPE(TXT)
ENDDO
/* Check for full path name on the command */
CALL PGM(QCLSCAN) PARM(&PATH &PATHLEN &STRPOS '/' +
&PATLEN '1' '0' '0' &PATLOC)
/* If not full path, use the current directory */
/* Else, use the path entered on the command */
IF COND(&PATLOC *EQ 0) THEN(DO)
RTVCURDIR RTNDIR(&CURDIR) DIRNAMLEN(&DIRLEN)
IF COND(%SST(&CURDIR &DIRLEN 1) *NE '/') +
THEN(CHGVAR VAR(&CURDIR) VALUE(&CURDIR +
*TCAT '/'))
CHGVAR VAR(&FULLPATH) VALUE(&CURDIR *TCAT &PATH)
ENDDO
ELSE CMD(CHGVAR VAR(&FULLPATH) VALUE(&PATH))
/* Copy stream file to source file in QTEMP. */
/* If the file does not exist, create it. */
CPYFRMSTMF FROMSTMF(&FULLPATH) +
TOMBR('/QSYS.LIB/QTEMP.LIB/@ED.FILE/SOURCE.+
MBR') MBROPT(*REPLACE)
MONMSG MSGID(CPFA0A9 CPFA095) EXEC(DO)
CPYTOSTMF +
FROMMBR('/QSYS.LIB/QTEMP.LIB/@ED.FILE/@NULL+
.MBR') TOSTMF(&FULLPATH) STMFOPT(*REPLACE)
CLRPFM FILE(QTEMP/@ED) MBR(SOURCE)
ENDDO
/* Edit the stream-now-source file in QTEMP */
STRSEU SRCFILE(QTEMP/@ED) SRCMBR(SOURCE)
/* If member in QTEMP has records, copy it back */
/* to stream file ... else, delete the stream file */
RTVMBRD FILE(QTEMP/@ED) MBR(SOURCE) NBRCURRCD(&NBRRECS)
IF COND(&NBRRECS *GT 0) THEN(DO)
CPYTOSTMF +
FROMMBR('/QSYS.LIB/QTEMP.LIB/@ED.FILE/SOURC+
E.MBR') TOSTMF(&FULLPATH) STMFOPT(*REPLACE)
ENDDO
ELSE CMD(DO)
DEL OBJLNK(&FULLPATH)
ENDDO
RETURN
ERROR:
FWDPGMMSG
MONMSG MSGID(CPF0000)
ENDPGM
LATEST COMMENTS
MC Press Online