Wednesday, January 22, 2020

Copying source statements from IFS files into programs

copy and include source code from members and ifs files into another member

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.

1 comment:

To prevent "comment spam" all comments are moderated.
Learn about this website's comments policy here.

Some people have reported that they cannot post a comment using certain computers and browsers. If this is you feel free to use the Contact Form to send me the comment and I will post it for you, please include the title of the post so I know which one to post the comment to.