Midware Ltd.

Variable Size Strings

Home
Services
News
AS/400
Employment

Sign-up for e-mail notifications

Take our weekly poll

Dow Jones Intraday

Nasdaq Intraday

 

 

Another powerful feature of ILE procedures is the ability to pass text strings of variable length.  For this example, lets write a procedure utility that will convert a text string to upper case.

We will allow a string up to 2048-bytes to be passed into the procedure, but we don't want to force the user to always have to pass a string of exactly 2048 bytes.  Passing variable length strings is one of those things where you would think there would be an easier way to do it, but there isn't.  Once you get the hang of it, it's not too bad though.

Therefore, we will use the *VARSIZE keyword on the parameter in the procedure interface and prototype.  The procedure will always return a 2048 byte string.  Our procedure interface looks like this:

D+++++++++++++++++++++++++++++++++++++++++++++++++++++++
D Uppercase       PI          2048     opdesc
D  @String                       8  0  const
D                                      options(*varsize)

The one and only parameter is a required constant.  There will be no error conditions, therefore we wont have a return code.

Notice the OPDESC keyword on the procedure interface.  This indicates that operational descriptors should be passed when the procedure is called.  Operational descriptors will allow us to retrieve the actual length of the passed string.  They are automatically passed without any additional coded from the user.

Recall that the default for passing parameters is by reference rather than by value.  This means that the address pointer of the field in memory is passed rather the actual value.   

If we call the Uppercase procedure with a parameter of Field2, it will actually pass the address pointer for the "T".  If we use the full 2048 bytes, we'll be using Field3, Field4, and so on.  Therefore, we need to determine the actual length of Field2.


CEEDOD API

To do this, use the CEEDOD API.  This is an IBM supplied procedure that retrieves the operational descriptors for a given parameter.  To use the API, first code the procedure prototype.  If you plan on calling this procedure in multiple modules (perhaps in the Lowercase procedure also), you should code the prototype in the global variables section.  You may even want to create a copybook member.

D++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
D ceedod          PR
D                               10i 0
D                               10i 0
D                               10i 0
D                               10i 0
D                               10i 0
D                               10i 0
D                               12a    options(*omit)

Unfortunately, the parameters we don't need are not optional, therefore, we need to set up dummy fields for them as well as the one parameter (variable length) that we do need.

D @DescType       S             10i 0
D @DataType       S             10i 0
D @DescInfo1      S             10i 0
D @DescInfo2      S             10i 0
D @ParamLength    S             10i 0

The first parameter of the procedure indicates which parameter of our procedure we want information about.  We will hardcode a 1 when calling the procedure to indicate we want the operational descriptors for the first (and only) parameter of the procedure.  We can *omit the last parameter for our purposes.  Calling the API looks like this:

callp     ceedod(1: @DescType: @DataType: @DescInfo1:
             @DescInfo2: @ParamLength: *omit)

In our example of passing Field2, @ParamLength will be set to 5.

Complete documentation of the CEEDOD API


Our global variable section of our procedure looks like this:

D ceedod          PR
D                               10i 0
D                               10i 0
D                               10i 0
D                               10i 0
D                               10i 0
D                               10i 0
D                               12a    options(*omit)

D @DescType       S             10i 0
D @DataType       S             10i 0
D @DescInfo1      S             10i 0
D @DescInfo2      S             10i 0
D @ParamLength    S             10i 0

D @Upper          C                    const('ABC...XYZ')
D @Lower          C                    const('abc...xyz')
D @NewString      S           2048
D @Len            S              4  0

Note that we have two constants to represent the entire uppercase and lowercase alphabet.  The procedure then looks like this:

P Uppercase       B                    export

D Uppercase       PI          2048     opdesc
D  @String                       8  0  const
D                                      options(*varsize)


 *
 * Determine length of parameter...
C                   c
allp     ceedod(1: @DescType:
C                             @DataType: @DescInfo1:
C                             @DescInfo2: @ParamLength:
C                             *omit)
C                   eval      @Len = @ParamLength

C                   eval      @NewString = *blanks
C                   if        @Len > 0
C                   eval      %subst(@NewString: 1: @Len) =
C                               %subst(@String: 1: @Len)

C     @Lower:@Upper xlate     @NewString    @NewString
C                   endif

C                   return    @NewString

P Uppercase       E

The first thing we do is determine the length of @String.  We then initialize our return value @NewString to blanks and load it with the contents of @String.  Lastly we use the XLATE function to convert lowercase characters to uppercase.


Because we took a little extra time to allow variable length strings, we now have a very useful function.

if        Uppercase(@StateCode) = 'NY'

eval      %subst(@FirstName: 1: 1) = 
             Uppercase(%subst(@FirstName: 1: 1))

  Back to Omitting Parameters

Next to Binder Language

 
Home Feedback Contents Search

Send mail to midware@midwareservices.com with questions or comments about this web site.
Copyright 2000 Midware, Ltd.

Last Modified:  September 11, 2000