In Part 1, we discussed service program signatures and defined the differences between current and previous signature levels. In this installment, we will discuss the very simple binder language and how you use it to create service program signatures.
How to use the binder language to manage signatures
The primary purpose of the binder language is to allow you to manage a service program's signatures. The language is made up of only three commands that must be entered in a strict sequence to make up logical units called export blocks. One signature is generated for each export block that you define. The binder language commands are listed below in the required sequence:
- STRPGMEXP. The Start Program Export command is used to start the definition of a new export block (i.e., a block of Export commands). It is also used to control the generation and type of the signature associated with the export block.
- EXPORT. The Export command is used to specify that a procedure or data item in the associated service program should be exported, that is made available to other programs and service programs. Procedures and data items that are not exported are considered private and cannot be used by other programs. The order in which the exports are listed is paramount in signature generation; system-generated signatures are created from the names and the order of exported items.
- ENDPGMEXP. The End Program Export command is used to end an export block.
Of the three binder language commands, the STRPGMEXP command is the only one that is even remotely complex. (EXPORT has only one parameter, and ENDPGMEXP doesn't have any.) The STRPGMEXP command has three parameters:
- Program level (PGMLVL). This parameter lets you specify whether the signature generated for this export block is the current signature or a previous signature. Valid values are *CURRENT and *PRV.
- Signature level check (LVLCHK). This parameter is inappropriately named. It does not control in any way the signature matching that the system does when the program is activated. When *NO is specified for this parameter, the system simply generates a signature consisting of all hex zeros -- a valid signature that must still match the signature in the client program. Specifying LVLCHK(*NO) is the equivalent to specifying LVLCHK(*YES) and SIGNATURE(x'00').
- Signature (SIGNATURE). This parameter lets you specify the signature value associated with this export block. The default value is *GEN, which instructs the system to generate the signature. The result is a hash of the names and order of the exports, producing a unique value that can be used to verify interface compatibility.
When you specify your own signature (or when you specify *NO for the LVLCHK parameter), it becomes your responsibility to make sure the programs that use the service program are compatible with its interface. The value *GEN is required when LVLCHK(*NO) is specified so that the system can guarantee that the special signature value of all hex zeros is properly generated.
I cannot emphasize enough that specifying LVLCHK(*NO) or hard-coding your own signature should be done only in extraordinary circumstances.
Understanding the importance of export blocks
The items listed in an export block (i.e., those procedures and data items specified on Export commands) are used not only to generate signatures but also to create a cross-reference table in the associated service program. Created solely from the *CURRENT level export block, this cross-reference table is known by many names, including export resolution table, exported symbol table and public interface. No matter what you call it, this table contains the names of all the items specified on the EXPORT commands in the order they were specified.
Remember: Only the *CURRENT level export block (not any of the *PRV level export blocks) is used to generate this table, which contains the names of the data items and procedures that are currently available for use from the associated service program.
The table also contains the addresses of (i.e., pointers to) all the exported items. For example, if a procedure called P1 is exported, its name is placed in the table along with a pointer to the actual procedure within the service program.
When a program that uses a service program is created (i.e., linked/bound), the export resolution table is searched to try to resolve procedure calls (and external data items). When a match is found, the index of that matching table entry is stored in the program. When the program is later run, the index is used to locate the associated pointer in the table. Access to the exported procedure (or data item) is then made through the pointer.
Using the P1 procedure as an example, suppose P1 is the fourth item in the export resolution table. When a program that calls P1 is created, the number 4 is stored in the program. When the program is run, that number 4 is used to locate the table entry that contains the pointer to the actual P1 procedure. The process is actually a bit more complicated, but the important thing to remember is that the name "P1" is not used after the linking process. Only the table index numbers and the pointers are used at run-time.
That is important because you can rename a service program procedure without needing to recreate the programs that call the procedure, as long as the new name remains in the same ordinal position within the *CURRENT export block.
How to create and edit binder language source
As with most iSeries languages, you create and edit binder language source using SEU. The default source file name for the binder language is QSRVSRC, and the source type (i.e., the member type) is BND. Prompting for the binder language commands is supported using a CL-type prompting method. That is, you type the command and then press F4 to prompt for the associated command parameters.
The names of the source file and member containing the binder language source for a particular service program are specified on the CRTSRVPGM command when you create the service program (or when you use the UPDSRVPGM command to update a service program).
To use binder language source when creating a service program, specify *SRCFILE on the EXPORT parameter on the CRTSRVPGM command. Then specify the source file name and member name on the SRCFILE and SRCMBR parameters, respectively. Since the default for the SRCMBR parameter is *SRVPGM, it is advisable to give the binder language source member the same name as the associated service program.
About the author: Ron Turull is editor of Inside Version 5. He has more than 20 years' experience programming for and managing AS/400-iSeries systems.