Newsletters Subscriptions Forums Media Kit About Us Contact Search Home

Stuff
OS/400 Edition
Volume 2, Number 21 -- October 23, 2003

Binder Source: The Little Language That Could


by Joel Cochran

In "Service Programs with a Smile" I explained how to make ILE program maintenance easier by creating service programs to manage procedure modules. In examples given in the article, I specified the EXPORT(*ALL) attribute. I also said this is not the best way to manage service programs, because of the maintenance challenges it creates. Maintenance is always an uphill battle, but you can make it a lot easier with help from a little language.

It's All in the Signature

Creating a service program with EXPORT(*ALL) is quick and easy because it only requires the CRTSRVPGM command. As a result, the service program will automatically export every "exported" procedure in the module list and make them available to any program that binds the service program. Simple and effective, so what's the big deal? As with many things, the big deal comes later in the life of the programs that bind the service program.

When a service program is created, the system assigns a 16-byte signature. To the naked eye, this signature appears random, but is actually generated by encoding the service program's EXPORT list. Say I have a service program with three procedures that I created:

CRTSRVPGM SRVPGM(MYLIB/MYSRVPGM) 
   MODULE(MYLIB/PROC1 MYLIB/PROC2 MYLIB/PROC3) 
      EXPORT(*ALL)

If I run the Display Service Program (DSPSRVPGM) command, I can see that the signature is something like D9D5C2D4C9E2C340F2F0F0F3F0F7F2F5. If I decide that I need to add a fourth procedure, I can easily recreate my service program:

CRTSRVPGM SRVPGM(MYLIB/MYSRVPGM) 
   MODULE(MYLIB/PROC1 MYLIB/PROC2 
      MYLIB/PROC3 MYLIB/PROC4) EXPORT(*ALL)

But now, since my EXPORT list changed, my signature is D9D5C2C3D6D4D440F2F0F0F3F0F4F2F5. The idea is like level checking on a file: when a program executes, it checks the current signature of the service program object against the signature found at creation time. If the two don't match, you'll get a runtime error: "signature violation occurred." The only way to correct this problem is to reset the signature, by either recreating the program or updating the program with MODULE(*NONE). Of course, if you have a hundred programs bound to that service program, that means a hundred additional steps, thus the maintenance problem. Fortunately, we can thank IBM for giving us a better method.

The Smallest Language in the World

With only three op codes and a handful of attributes, the binder source language must be the smallest language in the world and is certainly one of the easiest to learn. In fact, one might argue that it is not really a language, because it has no logic and no variables, it can't be compiled, and it doesn't even have an object type. I think of it more as a supporting configuration file, but if IBM calls it a language I'll give it the benefit of the doubt.

Binder source allows you to specify a list of procedures to be exported by the service program. These procedures must exist in the modules referenced inside the module list on the CRTSRVPGM command. Create a source member, usually in a source file called QSRVSRC, with a type of BND, and add the binder source. The code is very simple, and looks something like this:

STRPGMEXP PGMLVL(*CURRENT)
  EXPORT SYMBOL(PROC1)
  EXPORT SYMBOL(PROC2)
  EXPORT SYMBOL(PROC3)
ENDPGMEXP

As I mentioned, the binder source language has only three op codes: STRPGMEXP, EXPORT, and ENDPGMEXP, and they are always used in that order, so let's go over each one.

STRPGMEXP

STRPGMEXP (or Start Program Export) signifies the beginning of an EXPORT list. (You can have more than one, which I'll discuss later.) It has three options: PGMLVL, LVLCHK, and SIGNATURE.

PGMLVL is required and has two possibilities, *CURRENT and *PRV. There must always be one, and only one, *CURRENT, which is the default. The *PRV allows you to maintain multiple export lists (more on this later).

LVLCHK has two options, *YES and *NO. No means your service program will have a signature value of 0, and for the life of me I cannot conceive of a scenario when I would be even remotely interested in using *NO. The default is *YES, and I recommend you leave it as such.

The last option, SIGNATURE, is really the heart of what makes binder source so cool. The default value is *GEN and will serve you just fine. Remember the funky 16-byte signatures I talked about earlier? Well, *GEN is what creates them. The cool thing is that, in conjunction with *PRV mentioned above, you can have multiple signatures per service program. As a result, the list can grow, meaning that the *CURRENT signature will change, but programs created with a *PRV signature can still run without modification. This backward compatibility is, after all, the whole point of using binder source.

EXPORT

The next code, EXPORT, tells the service program to export this procedure. There are two ways to do so, either with or without quotation marks. With the quotation marks, the procedure name will be searched for in the case it is entered, so EXPORT('myProc') is not the same as EXPORT('MYPROC'). I'm not a C programmer, but since we are dealing with ILE here, I'm sure this feature is to allow mixed-case procedure names. Not using quotes will automatically search for the name in uppercase, so EXPORT(myProc) does equate to EXPORT(MYPROC). For RPG IV procedures, there is no reason not to use the non-quotes approach.

ENDPGMEXP

The last op code couldn't be simpler: ENDPGMEXP stands for End Program Export, and has no options.

I think I can, I think I can. . .

When you create the service program the command changes a little:

CRTSRVPGM SRVPGM(MYLIB/MYSRVPGM) 
   MODULE(MYLIB/PROC1 MYLIB/PROC2 MYLIB/PROC3 MYLIB/PROC4) 
      EXPORT(*SRCFILE) SRCFILE(MYLIB/QSRVSRC MYSRVPGM)

The important thing to remember is that it's all about the signature: this process will produce the same signature as the original method of EXPORT(*ALL). I know what you're thinking: yes, it's a longer command, and you have another source member to deal with, and another language to boot, and you end up with exactly the same signature. So what's the big deal? The big deal is that you are not limited to only one EXPORT list.

Let's revisit the idea of adding PROC4 to this service program. The easiest way to do so is to copy the existing *CURRENT block and change *CURRENT to *PRV and add our new procedure to the end of the *CURRENT block, like so:

STRPGMEXP PGMLVL(*CURRENT)
  EXPORT SYMBOL(PROC1)
  EXPORT SYMBOL(PROC2)
  EXPORT SYMBOL(PROC3)
  EXPORT SYMBOL(PROC4)
ENDPGMEXP

STRPGMEXP PGMLVL(*PRV)
  EXPORT SYMBOL(PROC1)
  EXPORT SYMBOL(PROC2)
  EXPORT SYMBOL(PROC3)
ENDPGMEXP

It is crucial that you do not reorder the procedures in either block! Signatures are generated by alphabetical order of the procedures, but, once generated, it is the relative position in the list that the program recalls. So reordering an existing list could have disastrous effects.

Now you have to create the service program again. There is no way around this step. You must run the CRTSRVPGM command over the new binder source and include PROC4 in the module list.

In the previous example, when we recreated the service program a new signature was generated, which meant we had to re-create all of our programs, but now we have eliminated that problem! By including the *PRV block, the previous signature is still valid, so programs created over the first block will continue to function without interruption. As they are recompiled, they will be assigned the *CURRENT signature. Even better is the fact that you can have all the *PRV lists you need; simply keep appending them, like so:

STRPGMEXP PGMLVL(*CURRENT)
  EXPORT SYMBOL(PROC1)
  EXPORT SYMBOL(PROC2)
  EXPORT SYMBOL(PROC3)
  EXPORT SYMBOL(PROC4)
  EXPORT SYMBOL(PROC5)
  EXPORT SYMBOL(PROC6)
  EXPORT SYMBOL(PROC7)
  EXPORT SYMBOL(PROC8)
ENDPGMEXP

STRPGMEXP PGMLVL(*PRV)
  EXPORT SYMBOL(PROC1)
  EXPORT SYMBOL(PROC2)
  EXPORT SYMBOL(PROC3)
  EXPORT SYMBOL(PROC4)
  EXPORT SYMBOL(PROC5)
  EXPORT SYMBOL(PROC6)
ENDPGMEXP

STRPGMEXP PGMLVL(*PRV)
  EXPORT SYMBOL(PROC1)
  EXPORT SYMBOL(PROC2)
  EXPORT SYMBOL(PROC3)
  EXPORT SYMBOL(PROC4)
ENDPGMEXP

STRPGMEXP PGMLVL(*PRV)
  EXPORT SYMBOL(PROC1)
  EXPORT SYMBOL(PROC2)
  EXPORT SYMBOL(PROC3)
ENDPGMEXP

Even through all these changes, the original program, created with the original three-procedure EXPORT list, will still run undaunted, because that signature is still valid. Just don't forget that there can only be one *CURRENT entry and that you should never change the order of the EXPORT list in any block.

Did I Mention Signatures?

This approach will work great with no modifications, but there is one more thing to take advantage of: you can specify your own signatures. Remember that the system will generate and assign a signature for each block in the binder source, but it is of no value to the human eye. I use the manual signature as an additional piece of documentation, like so:

STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('MYNAME 20031001')
  EXPORT SYMBOL(PROC1)
  EXPORT SYMBOL(PROC2)
  EXPORT SYMBOL(PROC3)
  EXPORT SYMBOL(PROC4)
ENDPGMEXP

STRPGMEXP PGMLVL(*PRV) SIGNATURE('MYNAME 20030425')
  EXPORT SYMBOL(PROC1)
  EXPORT SYMBOL(PROC2)
  EXPORT SYMBOL(PROC3)
ENDPGMEXP
</CODE>

This will replace the system-generated signature D9D5C2C3D6D4D440F2F0F0F3F0F4F2F5 with the EBCDIC encoding of the first 16 bytes of MYNAME 20031001. This is a good way to track change dates because, in your binder source, you now have some meaningful documentation. There is some debate concerning the value of this approach, but it is not harmful; just remember to change the *CURRENT block's signature when you add a new procedure.

A Quick Note On Service Program Design

There are several different approaches to creating service programs. The example used in this article and the last assumes that you are using the "one-procedure per module" approach. Each procedure listed has its own source member and *MODULE object. I tend to prefer this method, since it is straightforward and is comfortable for experienced RPG programmers.

Sometimes, though, it can be a pain if you are working with service programs that house many modules. Because of the one-to-one relationship, you have to manually list each module on the CRTSRVPGM command. At creation time, the command looks for all the procedures listed for EXPORT (either *ALL or as specified in your binder source) in the modules listed. As a result, you can use multiple procedure modules, and as long as the procedures in the export list are present, all is well. Many people use this "many procedures per module" approach, and it is very effective. While this is not my preference, there is something to be said for shared resources and collocated source for related procedures. The ultimate truth is that it doesn't matter: once created, the *SRVPGM object is completely independent of its constituent *MODULE objects.

You should be aware that when a program opens a service program, it opens the entire program, not just the procedures it uses. As a result, in theory, excessively large service programs may hamper performance. I have yet to see this cause a problem, but it seems logical and is worth remembering. For this reason, and for general orderliness, I prefer to organize service programs into groups of like procedure: for example, one for string operations and one for math operations.

And the Little Engine Did

Binder source may not be an impressive language with lots of functionality, but it certainly makes maintaining service programs a whole lot easier. And just like the little engine that could, we all can get up that maintenance hill if we just try!

In my next article, I'll discuss how to use binding directories and /copy books to create a simple and effective maintenance approach by extending the RPG language.


Joel Cochran is the director of research and development for a small software firm in Staunton, Virginia, and is the author and publisher of www.RPGNext.com. E-mail: joel@rpgnext.com


Sponsored By
BUG BUSTERS SOFTWARE ENGINEERING

Software You Need Now!
· Communications
· Object distribution
· Remote support
· CD mastering
· Security
· Internet newsgroups
· Web chat and forum servers
· Dynamic menus

Bug Busters has been providing quality software solutions for the iSeries and AS/400 since 1988.

Download Free Thirty-Day Trials:
www.bugbusters.net



THIS ISSUE
SPONSORED BY:

Damon Technologies
Bug Busters Software Engineering
WorksRight Software
Profound Logic Software


BACK ISSUES

TABLE OF
CONTENTS
Staggering SQL String Handling with Regular Expressions

Binder Source: The Little Language That Could

Control Access Path Rebuilding

OS/400 Alert: OS/400 Passwords Can Be Seen


Editors
Shannon O'Donnell
Kevin Vandever

Managing Editor
Shannon Pastore

Contributing Editors:
Howard Arner
Raymond Everhart
Joe Hertvik
Ted Holt
Marc Logemann
David Morris

Publisher and
Advertising Director:

Jenny Thomas

Advertising Sales Representative
Kim Reed

Contact the Editors
Do you have a gripe, inside dope or an opinion?
Email the editors:
editors@itjungle.com


Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved.