Figure 1 shows the code of a calling program. It calls PGMB passing Parm1, a 10 character field, as a parameter. Figure 1: A program call with a parameter field in a data structure Figure 2 shows the code of the called program. It has an incorrect length of 15 for Parm1. Will the compiler tell us that it is invalid? No. Will the program fail at run time? No. What will happen? When control returns to the calling program, Parm1 will have a value of 'ZZZZZZZZZZ' and Parm2 will have a value of 'ZZZZZYYYYY'. Just imagine the fun if Parm2 was a packed numeric field. Figure 2: The called program with an invalid length for a parameter. You really want the compiler to validate the parameter list for you, which is one of the reasons for using prototypes. The Prototype
'); // -->
is the format, or the template, or the rules, for the call operation. It is not a parameter list. Prototypes are defined on the D specifications, as shown in Figure 3. The format of a prototype is very similar to a data structure, except that the type is PR as opposed to DS. You can provide your own name for the CALLP (PromptProduct). The EXTPGM keyword indicates that this is the equivalent of a CALL operation, and it identifies the name of the called program (PRP01R). The names of the subfields in the prototype are irrelevant, what are important are the number of subfields (i.e. parameters) and the definition of each. In the example in Figure 3 the compiler will ensure that two parameters are passed, that Parm1 is a 30 character field and that Parm2 is a 1 character field. Figure 3: A prototyped call to a program. I quite like the ability to use a meaningful name on the call. The Procedure Interface Figure 4: A Procedure Interface. Since the prototype is required in at least two programs, it makes sense to put it in a copy member and include it using the /COPY compiler directive. And it makes even more sense to put all prototypes in a single copy member and include it in all programs using a /COPY compiler directive. Think of this as the source member containing the rules for all calls within your application. Keywords Figure 5: Using a work field on a parameter list When using a prototyped call, you can use the CONST keyword to indicate that a constant value can be passed for the parameter, as shown in Figure 6. Figure 6: Passing a constant value as a parameter. Of course, you must make sure that the called program does not change the second parameter. If you are using a procedure interface, in the called program, the compiler will give you an error if you try to change a parameter that has a CONST keyword. Another useful keyword is OPTION with a value of *OMIT or *NOPASS. Figure 8 shows an example of calling a program to set a customer name and address. The name is optional, as are the second and third address lines. OPTION(*OMIT) indicates that a value of *OMIT can be used in place of a parameter. OPTION(*NOPASS) indicates that the parameter is optional. Once a parameter is defined with OPTION(*NOPASS), all following parameters must be defined with OPTION(*NOPASS). All three calls are valid. Figure 7: A prototypes call using *OMIT and *NOPASS. Figure 8 shows a snippet of the called program. The name and address lines are set to their "default" values. The %ADDR BIF is used to check whether or not *OMIT was specified for the name; the address will be null if *OMIT was specified. The %PARMS BIF is used to check the number of parameters passed. Figure 8: Checking for *OMIT and *NOPASS in a called program. Conclusion Also, if at a later stage, you decide to change any of these programs to subprocedures, all you need to do is change the EXTPGM keyword to an EXTPROC keyword and compile accordingly. ---------------------------
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| iSeries Security - Security Tools, Physical Security and System Security |
| About Us | Contact Us | For Advertisers | For Business Partners | Site Index | RSS |
|
|
|
|||||||