I am sure we are all familiar with using a copy compiler directive to copy source code from a "copy book" source member into another. As we can now edit and compile individual source files in the IFS, how can I insert code from those members into the source code of my source file members?
Below I am going to give examples in my three favorite IBM i programming languages:
I have three files in an IFS folder, MyFolder, that contain snippets of RPG, CL, and SQL that I want to copy into programs in a source file, DEVSRC, in my library, MYLIB. I also have code snippets in other source members I want to include too. How to do it?
RPG
This will work for IBM i 7.3 and greater.
In an earlier post I gave examples of using RPG compiler directives including the ones used to copy source from one source member to another. The /COPY directive has been around for as long as I have programmed in the RPG language. It has been joined by the /INCLUDE directive, that does the same. What does this look like?
Let me start with the source member snippet, RPGCPYMBR:
01 **free 02 FromMbr = *on ; |
Line 1: I need to have the **FREE as the RPG code within starts in the first position of the source member. If I do not have this in the source member the program that this is copied/included into will not compile.
Line 2: Just moving the value of *ON into an indicator variable.
The source member in the IFS folder is called RpgCopy.rpgle. I have created it with the "rpgle" file extension, but anything will do here including "txt".
01 **free 02 FromIFS = *on ; |
This is the same as the "copybook" source member, just with a different indicator.
The source code for the program looks like:
01 **free 02 dcl-s FromIFS ind ; 03 dcl-s FromMbr ind ; 04 /copy mylib/devsrc,rpgcpymbr 05 /copy '/myfolder/rpgcopy.rpgle' 06 /include mylib/devsrc,rpgcpymbr 07 /include '/myfolder/rpgcopy.rpgle' |
Line 2 and 3: I have defined the indicator variables that are in the snippets in the main source member of the program.
I wanted to give examples of using the both the /COPY and /INCLUDE as this is possible with both.
Lines 4 and 6: Personally I prefer to give the library and source file when copying/including from a source member. But you do not have to, the post about RPG compiler directives gives other examples of allowed formats.
Line 5 and 7: The path to the file that contains the snippet I want to copy/include is enclosed with apostrophes ( ' ). I do find it interesting that the path I give is not case sensitive even though the folder is MyFolder and the file is RpgCopy.rpgle, I would have thought the given path would be case specific but it does not.
When I compile the program and I look in the compile listing I can see that my member and IFS files were copied/included into the program:
000800 /include mylib/devsrc,rpgcpymbr *---------------------------------------------- * RPG member name . : RPGCPYMBR * External name . . : MYLIB/DEVSRC(RPGCPYMBR) * Last change . . . : DD/DD/DD TT:TT:TT *---------------------------------------------- Seq <---------------- Source Specifications --- Number ....+....1....+....2....+....3....+....4... 000100+**free 000200+FromMbr = *on ; 000900 /include '/myfolder/rpgcopy.rpgle' *---------------------------------------------- * RPG member name . : rpgcopy.r+ * External name . . : /myfolder/rpgcopy.rpgle * Last change . . . : DD/DD/DD TT:TT:TT *---------------------------------------------- Seq <---------------- Source Specifications --- Number ....+....1....+....2....+....3....+....4... 000001+**free 000002+FromIFS = *on ; 001000 |
CL
This will work for IBM i 7.3 and greater.
I did mention the Include source command, INCLUDE, in passing in an earlier post showing how it could be used to include a subroutine into any CL program. The program and snippets to be copied are the CL version of what I did with RPG.
The source member CLCPYMBR just contains one line of code:
01 CHGVAR VAR(&FROM_MBR) VALUE('1') |
The IFS file, ClCopy.clle in the IFS folder MyFolder, also contains just one line:
01 CHGVAR VAR(&FROM_IFS) VALUE('1') |
The source code for the CL program is straight forward:
01 PGM 02 DCL VAR(&FROM_IFS) TYPE(*LGL) 03 DCL VAR(&FROM_MBR) TYPE(*LGL) 04 INCLUDE SRCMBR(CLCPYMBR) SRCFILE(MYLIB/DEVSRC) 05 INCLUDE SRCSTMF('/myfolder/clcopy.clle') 06 ENDPGM |
Line 4: If I am including from a source member then I must give the source member, source file, and library.
Line 5: If I am including from an IFS file I use the "Source stream file" parameter. The path name I enter here is not case sensitive.
After I have compiled the CL program the compile listing shows that the contents from the source member and IFS file have been included:
/* START INCLUDE SRCMBR(CLCPYMBR) SRCFILE(MYLIB/DEVSRC) */ CHGVAR VAR(&FROM_MBR) VALUE('1') /* END INCLUDE SRCMBR(CLCPYMBR) SRCFILE(MYLIB/DEVSRC) */ /* START INCLUDE SRCSTMF('/myfolder/clcopy.clle') */ CHGVAR VAR(&FROM_IFS) VALUE('1') /* END INCLUDE SRCSTMF('/myfolder/clcopy.clle') */ |
SQL
This will work for IBM i 7.2 and greater.
Before I start making my copy member and IFS file I am going to need a very simple DDL Table to insert rows into:
CREATE TABLE QTEMP.TESTFILE (VALUE INT) |
This statement creates a table, TESTFILE, in QTEMP that just contains one column, VALUE, that is an integer type column.
My source file member, SQLCPYMBR is going to insert one row in this Table:
01 INSERT INTO QTEMP.TESTFILE VALUES(1) ; |
The file I created in my IFS folder, SqlCopy.sql, just contains another Insert statement:
01 INSERT INTO QTEMP.TESTFILE VALUES(2) ; |
This is the source member, SQLTEST, containing SQL statements into which I want to include the contents of these two:
01 BEGIN 02 DELETE FROM QTEMP.TESTFILE ; 03 INCLUDE SQL MYLIB/DEVSRC(SQLCPYMBR) ; 04 INCLUDE SQL '/MYFOLDER/SQLCOPY.SQL' ; 05 END ; |
Line 1: I need to "begin" this section of code. Notice that the BEGIN is not followed by a semi colon ( ; ).
Line 2: This Delete statement deletes the contents of the table.
Line 3: The Include statement includes the contents of the source member into here.
Line 4: This Include statement includes the contents from the file in the IFS. Yet again this is not case sensitive.
Line 5: End of the section of code.
I can execute this code just by using the Run SQL Statements command, RUNSQLSTM:
RUNSQLSTM SRCFILE(MYLIB/DEVSRC) SRCMBR(SQLTEST) |
I having not compiled this code, just executed the statements. The Include statements perform the statements contained within too. When I use a Select statement to view the contents of TESTFILE I can see the records inserted by the Insert statements that were in the included member and IFS file:
SELECT * FROM QTEMP.TESTFILE VALUE ----- 1 2 |
These examples are deliberately extremely simple, but they do show how to use the copy and include in these languages. I am sure you can think of more useful examples you can use these in your own work.
You can learn more about this from the IBM website:
This article was written for IBM i 7.4, and will work for the earlier releases mentioned.
I'd use relative paths whereever possible.
ReplyDelete