Until the last round of Technical Refreshes, IBM i 7.2 TR 7 and 7.3 TR 3, I could not find a way to retrieve the name of the procedure that I was in. The program data structure enticed me with the *PROC keyword. This was not the procedure's name, but rather either the program's or module's name.

01 DPgmDs SDS qualified 02 D ProcName *PROC 01 dcl-ds PgmDs psds qualified ; 02 ProcName *proc ; 03 end-ds ;

Fortunately these two Technical Refreshes introduced a new built in function, BiF , to returns the name of the current procedure: %PROC

This example is of what I call a closed subprocedure and how this new BiF works.

01 **free 02 ctl-opt dftactgrp(*no) ; 03 dcl-ds PgmDs psds qualified ; 04 ProcName *proc ; 05 end-ds ; 06 dcl-s ProcedureName1 char(100) ; 07 dcl-pr SomeProcedureThatDoesSomething ; 08 end-pr ; 09 ProcedureName1 = %proc() ; 10 SomeProcedureThatDoesSomething() ; 11 *inlr = *on ; 12 dcl-proc SomeProcedureThatDoesSomething ; 13 dcl-pi *n ; 14 end-pi ; 15 dcl-s ProcedureName2 char(100) ; 16 ProcedureName2 = %proc() ; 17 dump(a) ; 18 end-proc ;

Line 1: Come on, what did you expect, this example is in totally free RPG.

Line 2: As this programs contains a subprocedure I need to state that this should not run in the default activation group.

Line 3: This is the program data structure. I am only interested in the *PROC subfield so I have only defined it, and ignored the rest.

Line 6: Procedure names can be longer than ten characters I have defined this variable as 100 long.

Line 7 and 8: As this is a closed subprocedure I need to define a procedure prototype for it.

Line 9: I am retrieving the procedure name from the %PROC BiF for the first time in the main body of the program.

Line 10: Here I call the subprocedure.

Line 12: This is the start of the subprocedure, and it ends on line 18.

Lines 13 and 14: As this is a closed subprocedure it needs a procedure interface. I never name my interfaces, hence the *N . As there are not parameters passed to or returned from this subprocedure the interface is "empty".

Line 15: By defining this variable within the subprocedure it is local and not shared outside of it.

Line 16: I retrieve procedure name, from the %PROC , into the variable.

Line 17: I am using DUMP operation code to emulate what would happen if an error had occurred within the subprocedure and the message had been answered with a D .

When I look in the dump spool file, QPPGMDMP , I see the following:

NAME ATTRIBUTES VALUE PGMDS DS PROCNAME CHAR(10) 'PGM1 ' PROCEDURENAME1 CHAR(100) 'PGM1 Local variables for subprocedure : SOMEPROCEDURETHATDOESSOMETHING NAME ATTRIBUTES VALUE PROCEDURENAME2 CHAR(100) 'SOMEPROCEDURETHATDOESSOMETHING

ProcName , from the program data structure, contains the name of the program, which is what I have come to expect. ProcedureName1 also contains the program's name as this variable was updated in the main body of the program. As ProcedureName2 was updated in the subprocedure it contains the name of the subprocedure.

If I use an open subprocedure %PROC returns the name of that procedure too, even when the variable is defined in the main body of the program.

01 **free 02 ctl-opt dftactgrp(*no) ; 03 dcl-ds PgmDs psds qualified ; 04 ProcName *proc ; 05 end-ds ; 06 dcl-s ProcedureName char(100) ; 07 SomeProcedureThatDoesSomething() ; 09 *inlr = *on ; 09 dcl-proc SomeProcedureThatDoesSomething ; 10 ProcedureName = %proc() ; 11 dump(a) ; 12 end-proc ; NAME ATTRIBUTES VALUE PGMDS DS PROCNAME CHAR(10) 'PGM2 ' Local variables for subprocedure : SOMEPROCEDURETHATDOESSOMETHING NAME ATTRIBUTES VALUE PROCEDURENAME CHAR(100) 'SOMEPROCEDURETHATDOESSOMETHING

What if I have a program that uses a Main procedure?

01 **free 02 ctl-opt main(Main) ; 03 dcl-pr Main extpgm('PGM3') ; 04 end-pr ; 05 dcl-ds PgmDs psds qualified ; 06 ProcName *proc ; 07 end-ds ; 08 dcl-proc Main ; 09 dcl-pi *n ; 10 end-pi ; 11 dcl-s ProcedureName char(100) ; 12 ProcedureName = %proc() ; 13 dump(a) ; 14 end-proc ;

While ProcName contains the program name, ProcedureName contains the name of the procedure, Main . I am going to have to rethink not naming my Main procedure as I need to give it a unique name that will be returned by %PROC .

NAME ATTRIBUTES VALUE PGMDS DS PROCNAME CHAR(10) 'PGM3 ' Local variables for subprocedure : MAIN NAME ATTRIBUTES VALUE PROCEDURENAME CHAR(100) 'MAIN

In this last example I have my %PROC in a procedure that is in a module.

01 **free 02 ctl-opt nomain ; 03 dcl-ds PgmDs extname('RPG4DS') psds qualified 04 end-ds ; 05 dcl-s ProcedureName char(100) ; 06 dcl-pr FirstProcedure char(1) ; 07 end-pr ; 08 dcl-proc FirstProcedure export ; 09 dcl-pi *n char(1) ; 10 end-pi ; 11 ProcedureName = %proc ; 12 PgmDs = PgmDs ; 13 dump(a) ; 14 return '1' ; 15 end-proc ;

Line 2: As this is a module, there is no main procedure.

Lines 3 and 4: In my programs I use an external definition for my program data structure. This way all the subfields are available to me when needed. The program data structure can only be defined once in the module, and must be defined outside of any procedures.

Line 5: I have defined the variable I will be using for the procedure name outside of any procedure. This way I can use it in all the procedures.

Lines 6 and 7: The procedure prototype. This procedure returns an one character value to whatever called it.

Line 8: The start of my procedure. I need the export so that the procedure will return the one character value to whatever called it.

Lines 9 and 10: As I said before I never give my procedure interfaces names. This is where I denote within the procedure that a value is being returned from it.

When I look in the print file generated by the dump I see the following information:

Program data structure subfields ModulePgm (positions 334 – 343): Program containing module ModuleProc (344 – 353): Module containing procedure ProcNme (1 – 10): Module or program name ProcedureName : Name retrieved from %PROC

NAME ATTRIBUTES VALUE PGMDS DS MODULEPGM CHAR(10) 'PGM5 ' MODULEPROC CHAR(10) 'MODULE1 ' PROCNME CHAR(10) 'MODULE1 ' PROCEDURENAME CHAR(100) 'FIRSTPROCEDURE

This new BiF is already making me reconsider the way I name my Main procedures. I could see me using it in subprocedures and procedures for diagnostic purposes. When the operator informs me they have answered an error message with a D I can look in the dump spool file for the current procedure name in the "standard variable" I choose to use with %PROC .

You can learn more about this from the IBM website: