Subprocedure Returns, part 1- simple returns

For many subprocedures, I only need to return a single value. It might be a number, a character, string or an array of the same type. Although a data structure is also considered to be a single value for return purposes, I discuss data structure returns in more detail in Subprocedure Returns, part 2. In this article, I'll simply show a subprocedure prototype that returns a simple value. There really is not a lot to say.

The sample code

The sample code is from my STRING module. The subprocedure prototype shown here is used to convert an input value to a corresponding hexadecimal string representation, suitable for printing or display. For example, if I call the subprocedure with the string value "A", I will get the string value "C1" returned, its EBCDIC hexadecimal representation.

     
      ****************************************************************
      *  Procedure STRING_convertToHexString
      *
      *  Convert an input character string to its equivalent
      *  hexadecimal string representation.
      *  (EBDCIC)
      *
      *  Example:
      *     Input string: AB12  Returned: x'C1C2F1F2'
      *
      *  Parameters
      *
      *    inputString - the input string to convert. Maximum
      *      length 512.
      *
      *  Returns
      *
      *    hexString - the hexadecimal representation of the
      *      input string
      ****************************************************************
     D STRING_convertToHexString...
     D                 pr                  like(Types.VARYING1024)
     D   inputString...
     D                                     like(Types.VARYING512)
     D                                     const

Parameter definitions

The subprocedure accepts one required parameter, inputString. After some thought, I assigned a maximum length of 512 to the input parameter. Because each byte in the input string will be converted to two bytes (two hex digits), I defined a return value exactly twice the length of the input parameter.

I actually had quite a time with the parameter definition, in terms of using a VARYING data type. The IBM ILE RPG Reference manual seems to encourage its use, as in this excerpt from the V5R2 manual:

Why You Should Use Variable-Length Fields: Using variable-length fields for temporary variables can improve the performance of string operations, as well as making your code easier to read since you do not have to save the current length of the field in another variable for %SUBST, or use %TRIM to ignore the extra blanks.

If a subprocedure is meant to handle string data of different lengths, using variable-length fields for parameters and return values of prototyped procedures can enhance both the performance and readability of your calls and your procedures. You will not need to pass any length parameters or use CEEDOD within your subrocedure (sic) to get the actual length of the parameter.

Given the recommendation, I wondered if I should code the subprocedure with the maximum length allowed. Since the maximum length of a character field is 65,535, I would have to make the input parameter 1 byte less than half of that, rounded down. This is one of the very few times when I am concerned about the compiled code, in terms of performance. In this case, I am unsure about how much memory the subprocedure requests at run-time. The value of using the VARYING data type is that it makes it easier to work with the data, but I don't want to set aside 65,535 bytes of memory when most of the time I will be converting 132 bytes or less. The performance issue I am concerned with is more an issue of resource usage, rather than processor usage. If I were to needlessly allocate thousands more bytes than needed, I would put my program in worse shape, in terms of its potential for being swapped out. If I later find out that there are no negative concerns with maximum length varying fields, I will probably have to create another subprocedure to handle the longer parameter, as the current subprocedure will already be in production.

Return value

The return value is simply defined on the subprocedure prototype (pr) statement, as it will also be on the procedure interface (pi) statement.

Like defines

Both the parameter and the return value are defined using like-defines, using field definitions in the Types data structure. I will describe this technique in more detail in a future article. For now, the code in the Types data structure looks like this:

     DTypes            ds                  qualified
     D                                     based(ptrNull)
     D VARYING512                   512    varying
     D VARYING1024                 1024    varying

Another option: return nothing

I also have subprocedures that don't return any value. These are somewhat unusual, as the point of calling a subprocedure is usually to affect something of interest for subsequent use. But there are times when I have subprocedures that I simply call, expecting nothing in return. In that case, there is nothing to define on the prototype and procedure interface statements.

Craig Pelkie
December 13, 2004