Guru: Enumerated Data Types In RPG
September 16, 2019 Ted Holt
IT has changed a lot since I entered the field several decades ago, but some things have not changed. I would read in those early days that COBOL was dead, and I read the same thing now. Yet COBOL is 60 years old and still going strong. Back then I heard RPG criticized as “Real Poor Garbage”. These days I hear it scorned as “legacy”, which I assume is supposed to mean the same thing. Yet today’s RPG is better than any of its predecessors for business programming.
RPG supposedly does not have the features of modern languages. Maybe not, but I have found that I can make RPG do what I need it to do anyway. One example is enumerated data types.
RPG has no special syntax for enumerated types, but the existing syntax works quite well. Here’s how it’s done.
Let’s say that we have a program that calls a subprocedure to process a batch of transactions of some sort. The subprocedure can operate in one of three modes:
- It can validate the data, i.e. check the data for errors.
- It can validate the data and post the data if it passes validation.
- It can skip validation and post the data.
Such a subprocedure would probably be part of a service program, but to simplify my example, I make it an internal subprocedure.
The subprocedure returns a status code to report the result to the caller. Possible status codes are:
- The subprocedure executed without error.
- The subprocedure executed, but had to make some assumptions, and therefore generated one or more warning messages.
- The subprocedure found an error condition.
Here’s a copybook in which these data types are defined.
**free dcl-s Action_t char(2) template; dcl-c Validate 'V '; dcl-c Post 'P '; dcl-c ValidateAndPost 'VP'; dcl-s RunStatus_t packed(1) template; dcl-c SuccessfulRun 0; dcl-c RunWithWarning 1; dcl-c RunFailed 2;
I’ve defined two datatypes: Action_t and RunStatus_t. I like to end the datatype names with _t. Notice the TEMPLATE keyword on each declaration to prevent the compiler from allocating memory.
For each datatype, I’ve defined a set of allowable values as constants. Since RPG is not case-sensitive, I prefer to make constants look like any other type of identifier.
Any source member that includes this copybook can define variables and functions of these data types.
Here’s an example caller:
**free /include copybooks,DataTypes dcl-s Stat like(RunStatus_t); dcl-s BatchNumber packed(3); Stat = ProcessBatch (BatchNumber: ValidateAndPost); if Stat = RunFailed; // do something to handle the error endif; dcl-proc ProcessBatch; dcl-pi ProcessBatch like(RunStatus_t); inBatch packed(3) const; inAction like(Action_t) const; end-pi; if (inAction = Validate or inAction = ValidateAndPost); // calcs to validate the data if . . . some error condition . . . return RunFailed; endif; endif; if (inAction = Post or inAction = ValidateAndPost); // calcs to post the data if . . . some error condition . . . return RunFailed; endif; endif; return SuccessfulRun; end-proc;
Notice the variable, function, and function parameter that are defined with these data types.
dcl-s Stat like(RunStatus_t); dcl-pi ProcessBatch like(RunStatus_t); inAction like(Action_t) const;
The compiler would not prevent me from assigning literals or comparing to literals, but I never do. I always refer to the constants.
return SuccessfulRun; if Stat = RunFailed;
One last point I’d like to make is that I can truly use these template variables as if they were real data types, at least in most cases. For instance, I can use one of the constants in the INZ keyword.
dcl-s Stat like(RunStatus_t) inz(RunFailed);
This is not foolproof. The compiler won’t stop me from assigning an invalid value to a variable or assigning a literal for one type to a variable of another compatible type. Avoiding such errors is a matter of discipline, but it’s not an egregious task, and usually the errors stick out like a sore thumb. For example, this looks reasonable:
Color = Blue;
But this does not:
Color = RunFailed;
The newer languages certainly have their place, but that doesn’t mean that we should dump RPG overnight under the theory that anything new has to be better than anything old. RPG is an effective business programming language, and believe it or not, can do a lot that some critics say it can’t do.