RPG Subprocedures are very cool

Sub-Procedures are very cool, if you like that kind of thing (which I do!)

Probably my favorite RPG enhancement over the years. Coming from RPG3/400 to RPGLE this is something you will definitely need to learn. It’s been used extensively everywhere I’ve worked since leaving the boundaries of ‘JBA’ code and Green screen land 🙂

RPG Sub procedures The Basics

Quite simply a sub-procedure is just like a sub-routine with a few key differences

  • you give it a name and then you can use like a %BIF
  • a sub-procedure has its own local variables - which dont affect anything else in the program
  • a sub-procedure can also use global variables (anything that is defined in the mainline of the code is called the GLOBAL level)
  • the best thing is -- a sub-procedure can be entered into a service program which is then shared to any program on the system that uses that service program. (more on service programs in the service program chapter of this course)

Here is a very simple example:

Imagine you wrote a sub-procedure that received a parameter of ‘customer number’ and it went and found the ‘customer email address’ and you decide to call this procedure ‘GetCustomerEmail’ then you would use it in your RPG like this:

namefield = GetCustomerEmail( CusNum );

and that would execute the procedure and return the name into the variable namefield.

now you could define that subprocedure in your program – right at the bottom, below any old subroutines.


Here is a slightly more complex example:

How to use a sub-procedure to easily do same thing in lots of programs. Lets say I have the need to check if I am running in Batch or Interactive?

I had this problem ages ago, so I added a sub-procedure to my main service program that would return a YES or NO when asked ‘am i running interactive’

You could code it in your RPG like this:

If InteractiveJob();
  // do something
endif;

The code for this sub-procedure might look like this:

subprocedure in classic rpg
or of course, we can write this exact same code in a cleaner RPG style, if we use modern free format RPGLE:
**FREE

// check if job is running interactive
Dcl-Proc InteractiveJob Export;
Dcl-PI *n Ind;
end-pi;

// retrieve job information (qusrjobi) api
Dcl-PR RetrieveJobInfo EXTPGM('QUSRJOBI');
  @Receive LIKE(JobStatus);
  @JobLength Int(10);
  @JobFormat Char(8);
  @JobName Char(26) CONST;
  @JobIndent Char(15) CONST;
  @ErrCode LIKE(APIERROR);
End-PR;

// data definition section
// procedure work variables
Dcl-S Interactive Ind;
Dcl-S JobLength Int(10) INZ(%SIZE(JobStatus));
Dcl-S JobFormat Char(8) INZ('JOBI0100');

// job status data-structure
Dcl-DS JobStatus;
  JobBytesRtn Int(10) OVERLAY(JobStatus:*NEXT);
  JobBytesAvl Int(10) OVERLAY(JobStatus:*NEXT);
  JobName Char(10) OVERLAY(JobStatus:*NEXT);
  JobUser Char(10) OVERLAY(JobStatus:*NEXT);
  JobNumber Char(6) OVERLAY(JobStatus:*NEXT);
  JobIdentifier Char(16) OVERLAY(JobStatus:*NEXT);
  JobStatusCode Char(10) OVERLAY(JobStatus:*NEXT);
  JobType Char(1) OVERLAY(JobStatus:*NEXT);
  JobSubtype Char(1) OVERLAY(JobStatus:*NEXT);
  JobReserv1 Char(2) OVERLAY(JobStatus:*NEXT);
  JobRunPriority Int(10) OVERLAY(JobStatus:*NEXT);
  JobTimeSlice Int(10) OVERLAY(JobStatus:*NEXT);
  JobDefaultWait Int(10) OVERLAY(JobStatus:*NEXT);
  JobPurge Char(10) OVERLAY(JobStatus:*NEXT);
End-DS;

// Use API to retrieve job running status

RetrieveJobInfo (JobStatus:JobLength:JobFormat: '*':' ':apiError);

If JobType = 'I';
  Interactive = *ON;
Else;
  Interactive = *OFF;
EndIf;

Return Interactive;

End-Proc;

Now we wouldn't want to add this bunch of code to everything we wrote that wanted to use it would we?

In the olden days we might have done it in a /COPYBOOK but this requires re-compilation of everything if we change the copybook. Thats smelly.

Luckily the solution to this "lots of code being repeated" problem is SERVICE PROGRAMS. More on *SRVPGM's in a later section of this lesson.

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}
>