
This is one of the IBM i enhancements that was released in version 7.6, but not in 7.5 TR6. This new table function, PROGRAM_RESOLVED_IMPORTS, allows me to get a list of all the imports for an ILE program or service program.
This Table function has four parameters:
- PROGRAM_LIBRARY: Library that contains the ILE program or service program. "*LIBL" is not supported.
- PROGRAM_NAME: Name of the ILE program or service program.
- OBJECT_TYPE: *PGM for ILE program, *SRVPGM for ILE service program.
- IGNORE_ERRORS: Optional. NO when an error is encounter an error is returned. YES a warning is returned, this is the default.
This looks like:
01 SELECT * 02 FROM TABLE(QSYS2.PROGRAM_RESOLVED_IMPORTS( 03 PROGRAM_LIBRARY => < program_library_name >, 04 PROGRAM_NAME => < program_name >, 05 OBJECT_TYPE => < *PGM or *SRVPGM >)) |
In my first example I have a program, TESTPGM1, that calls various procedures in a service program, SRVPGM1.
TESTPGM1 looks like:
01 **free 02 ctl-opt main(Main) bnddir('TESTPGM1') ; 03 /copy devsrc,copybook ; 04 dcl-proc Main ; 05 dcl-s Returned char(10) ; 06 Returned = First() ; 07 Returned = Second('X') ; 08 Returned = Third() ; 09 return ; 10 end-proc ; |
Line 2: I am using a Main procedure called Main. And I will be using a binding directory for the list of objects to bind to this program.
Line 3: Copy the contents of the member copybook into this program. This will copy all the procedure definitions, DCL-PR, into the source.
Line 4: Start of the Main procedure.
Line 5: Defining a variable to contain what is returned from the service program's procedures.
Lines 6 - 8: Calling procedures in the service programs. Second needs to be passed a parameter, others do not. The result is placed in the variable Returned. For this example what those values are is immaterial.
I can the see the contents the of the TESTPGM1 binding directory using the BINDING_DIRESTORY_INFO View:
01 SELECT ENTRY_LIBRARY,ENTRY,ENTRY_TYPE, 02 ENTRY_ACTIVATION 03 FROM QSYS2.BINDING_DIRECTORY_INFO 04 WHERE BINDING_DIRECTORY_LIBRARY = 'MYLIB' 05 AND BINDING_DIRECTORY = 'TESTPGM1' |
I am only interested in the same columns that appear using the Work with Binding Directory Entries command, WRKBNDDIRE.
The result is:
ENTRY_ ENTRY_ ENTRY_ LIBRARY ENTRY TYPE ACTIVATION ------- ------- ------- ---------- *LIBL SRVPGM1 *SRVPGM *IMMED |
There is only the service program SRVPGM1 in the binding directory that will be bound to TESTPGM1 when it is created.
The procedures in the procedure look like:
01 **free 02 ctl-opt nomain reqprexp(*no) ; 03 dcl-proc First export ; | 04 end-proc ; 05 dcl-proc Second export ; | 06 end-proc ; 07 dcl-proc Third export ; | 08 end-proc ; |
Line 2: The module for the service program's module does not have a main procedure. The REQPREXP(*NO) means that I do not need procedure prototypes for these procedures.
What happens within the procedures is not needed. All the procedures have been marked as EXPORT, therefore, I can call them from TESTPGM1.
Now I can use the PROGRAM_RESOLVED_IMPORTS Table function to which exports TESTPGM1 uses. My statement is:
01 SELECT * 02 FROM TABLE(QSYS2.PROGRAM_RESOLVED_IMPORTS( 03 PROGRAM_LIBRARY => 'MYLIB', 04 PROGRAM_NAME => 'TESTPGM1', 05 OBJECT_TYPE => '*PGM')) |
Line 3: My program is in the library MYLIB.
Line 4: The program's name is TESTPGM1.
Line 5: And it is a program.
I have not given the IGNORE_ERRORS parameter as the default is 'YES'.
The results are:
BOUND_ RESOLVED SERVICE_ BOUND_ SERVICE_ RESOLVED_ PROGRAM_ SERVICE PROGRAM_ RESOLVED_ SYMBOL_ LIBRARY PROGRAM LIBRARY SYMBOL_NAME USAGE -------- -------- -------- --------------------- -------- *LIBL SRVPGM1 MYLIB THIRD *PROCEXP *LIBL SRVPGM1 MYLIB SECOND *PROCEXP *LIBL SRVPGM1 MYLIB FIRST *PROCEXP QSYS QRNXIE QSYS _QRNX_INIT_H *PROCEXP QSYS QRNXIE QSYS _QRNX_G_CANCEL_H *PROCEXP QSYS QRNXIE QSYS _QRNX_G_FC_H *PROCEXP QSYS QRNXIE QSYS _QRNX_G_INFSR_H *PROCEXP QSYS QRNXIE QSYS _QRNX_CALL_FC_H *PROCEXP QSYS QRNXIE QSYS _QRNX_CALL_EN_H *PROCEXP QSYS QRNXIE QSYS _QRNX_TERM_H *PROCEXP QSYS QRNXIE QSYS _QRNX_CAN_EXC_H *PROCEXP QSYS QRNXIE QSYS _QRNX_DFT_ERROR *PROCEXP QSYS QRNXIE QSYS _QRNX_INIT *PROCEXP QSYS QRNXIE QSYS _QRNX_SIGNAL_EXCP *PROCEXP QSYS QLEAWI QSYS Q LE leDefaultEh2 *PROCEXP QSYS QLEAWI QSYS Q LE leBdyCh2 *PROCEXP QSYS QLEAWI QSYS Q LE leBdyEpilog2 *PROCEXP QSYS QRNXUTIL QSYS _QRNX_GET_ASSOC_CCSID *PROCEXP |
The first three results are from the SRVPGM1 service program. The rest of the exports were included into the program by the compiler.
When I use PROGRAM_RESOLVED_IMPORTS with SRVPGM1:
01 SELECT * 02 FROM TABLE(QSYS2.PROGRAM_RESOLVED_IMPORTS( 03 PROGRAM_LIBRARY => 'MYLIB', 04 PROGRAM_NAME => 'SRVPGM1', 05 OBJECT_TYPE => '*SRVPGM')) |
Line 3: The service program is in the library MYLIB.
Line 4: The service program's name is SRVPGM1.
Line 5: And it is a service program.
The results returned are:
BOUND_ RESOLVED SERVICE_ BOUND_ SERVICE_ RESOLVED_ PROGRAM_ SERVICE PROGRAM_ RESOLVED_ SYMBOL_ LIBRARY PROGRAM LIBRARY SYMBOL_NAME USAGE -------- -------- -------- --------------------- -------- QSYS QRNXIE QSYS _QRNX_INIT_H *PROCEXP QSYS QRNXIE QSYS _QRNX_INIT *PROCEXP QSYS QLEAWI QSYS Q LE leDefaultEh2 *PROCEXP QSYS QRNXUTIL QSYS _QRNX_GET_ASSOC_CCSID *PROCEXP |
These are the imported procedures included into the service program when it is created.
In my next example the service program, SRVPGM2, has an import to another services program.
The program's, TESTPGM2, source looks like:
01 **free 02 ctl-opt main(Main) bnddir('TESTPGM2') ; 03 dcl-pr Another char(10) ; 04 end-pr ; 05 dcl-proc Main ; 06 dcl-s Returned char(10) ; 07 Returned = Another() ; 08 return ; 09 end-proc ; |
Line 2: This program also has a Main procedure. It also uses a binding directory, which is different from the one used by the previous program.
Lines 3 and 4: The procedure prototype for the procedure, Another, I will be calling.
Line 5: The start of the Main procedure.
Line 6: Definition of the variable to contain what is returned from the Another procedure.
Line 7: The Another procedure is called, and what is returned is placed in the variable Returned.
I can check for the contents of the binding directory using the BINDING_DIRECTORY_INFO again:
01 SELECT ENTRY_LIBRARY,ENTRY,ENTRY_TYPE, 02 ENTRY_ACTIVATION 03 FROM QSYS2.BINDING_DIRECTORY_INFO 04 WHERE BINDING_DIRECTORY_LIBRARY = 'MYLIB' 05 AND BINDING_DIRECTORY = 'TESTPGM2' |
This shows that there is just one entry, for the service program SRVPGM2.
ENTRY_ ENTRY_ ENTRY_ LIBRARY ENTRY TYPE ACTIVATION ------- ------- ------- ---------- *LIBL SRVPGM2 *SRVPGM *IMMED |
The source of the service program look like:
01 **free 02 ctl-opt nomain reqprexp(*no) bnddir('SRVPGM3') ; 03 dcl-pr Four char(10) ; 04 end-pr ; 05 dcl-proc Another export ; 06 dcl-pi *n char(10) ; 07 end-pi ; 08 dcl-s Var char(10) ; 09 Var = Fourth() ; 10 return Var ; 11 end-proc ; |
Line 2: Along with the NOMAIN and REQPREXP(*NO) I now have a binding directory. When the module is created this service program will be bound to it.
Lines 5: The procedure Another is for export.
Line 6 and 7: The procedure interface, which is just to return a ten character value to whatever called it.
Line 9: Call the procedure Fourth, that is in the service program, SRVPGM3.
The binding directory SRVPGM3 contains the following entry:
ENTRY_ ENTRY_ ENTRY_ LIBRARY ENTRY TYPE ACTIVATION ------- ------- ------- ---------- *LIBL SRVPGM3 *SRVPGM *IMMED |
Using PROGRAM_RESOLVED_IMPORTS for TESTPGM2:
01 SELECT * 02 FROM TABLE(QSYS2.PROGRAM_RESOLVED_IMPORTS( 03 PROGRAM_LIBRARY => 'MYLIB', 04 PROGRAM_NAME => 'TESTPGM2', 05 OBJECT_TYPE => '*PGM')) |
The results are:
BOUND_ RESOLVED SERVICE_ BOUND_ SERVICE_ RESOLVED_ PROGRAM_ SERVICE PROGRAM_ RESOLVED_ SYMBOL_ LIBRARY PROGRAM LIBRARY SYMBOL_NAME USAGE -------- -------- -------- --------------------- -------- *LIBL SRVPGM2 MYLIB ANOTHER *PROCEXP QSYS QRNXIE QSYS _QRNX_INIT_H *PROCEXP QSYS QRNXIE QSYS _QRNX_G_CANCEL_H *PROCEXP QSYS QRNXIE QSYS _QRNX_G_FC_H *PROCEXP QSYS QRNXIE QSYS _QRNX_G_INFSR_H *PROCEXP QSYS QRNXIE QSYS _QRNX_CALL_FC_H *PROCEXP QSYS QRNXIE QSYS _QRNX_CALL_EN_H *PROCEXP QSYS QRNXIE QSYS _QRNX_TERM_H *PROCEXP QSYS QRNXIE QSYS _QRNX_CAN_EXC_H *PROCEXP QSYS QRNXIE QSYS _QRNX_DFT_ERROR *PROCEXP QSYS QRNXIE QSYS _QRNX_INIT *PROCEXP QSYS QRNXIE QSYS _QRNX_SIGNAL_EXCP *PROCEXP QSYS QLEAWI QSYS Q LE leDefaultEh2 *PROCEXP QSYS QLEAWI QSYS Q LE leBdyCh2 *PROCEXP QSYS QLEAWI QSYS Q LE leBdyEpilog2 *PROCEXP QSYS QRNXUTIL QSYS _QRNX_GET_ASSOC_CCSID *PROCEXP |
The first result is for the Another procedure in SRVPGM2.
When I use PROGRAM_RESOLVED_IMPORTS for SRVPGM2:
01 SELECT * 02 FROM TABLE(QSYS2.PROGRAM_RESOLVED_IMPORTS( 03 PROGRAM_LIBRARY => 'MYLIB', 04 PROGRAM_NAME => 'SRVPGM2', 05 OBJECT_TYPE => '*SRVPGM')) |
The first result is for the procedure Fourth in SRVPGM3:
BOUND_ RESOLVED SERVICE_ BOUND_ SERVICE_ RESOLVED_ PROGRAM_ SERVICE PROGRAM_ RESOLVED_ SYMBOL_ LIBRARY PROGRAM LIBRARY SYMBOL_NAME USAGE -------- -------- -------- --------------------- -------- *LIBL SRVPGM3 MYLIB FOURTH *PROCEXP QSYS QRNXIE QSYS _QRNX_INIT_H *PROCEXP QSYS QRNXIE QSYS _QRNX_INIT *PROCEXP QSYS QLEAWI QSYS Q LE leDefaultEh2 *PROCEXP QSYS QRNXUTIL QSYS _QRNX_GET_ASSOC_CCSID *PROCEXP |
PROGRAM_RESOLVED_IMPORTS Table function is going to prove a useful too for determining which procedures a program or service program uses in another service program.
You can learn more about the PROGRAM_RESOLVED_IMPORTS Table function from the IBM website here.
This article was written for IBM i 7.6.
No comments:
Post a 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.