ILE RPG/400 CONTENTS 1. Introduction to ILE 1.1. What is ILE? 1.2. Advantages of ILE 1.3. History of ILE 1.3.1. Original program model (OPM) 1.3.2. Extended program model (EPM) 1.3.3. Integrated language Environment (ILE) 1.4. ILE Concepts 1.4.1. Procedures 1.4.2. Module 1.4.3. ILE program 1.4.4. ILE service program 1.4.5. Binding directory 1.4.6. Activation 1.4.7. Activation group 2. Introduction to ILE RPG/400 programming 2.1. RPGIV specifications 2.2. Cycle programming 2.3. Example of an ILE RPGIV program 2.4. ILE Improvements over OPM to RPGIV users 2.4.1. Program creation (Compilation) 2.4.1.1. Create a program usign CRTBNDRPG to maximize OPM compatibility 2.4.1.2. Create an ILE program using CRTBNDRPG 2.4.1.3. Create an ILE program using CRTRPGMOD and CRTPGM 2.4.1.4. Compiler listing 2.4.2. Program management 2.4.3. Program call (Execution) 2.4.3.1. Parameter passing syle 2.4.4. Source debugging 2.4.5. Bindable application program interface(APIs) 2.5. Data types 3. Op-Code variations in ILE RPG/400 over RPG/400 3.1. Arithmetic operations 3.2. Branching operations 3.3. Call operations 3.4. Date operations 3.5. Moving Date-Time data 3.6. Operations using Expressions 3.7. Message operation 3.8. String operations 3.9. Structured programming operations 4. File handling in ILE RPG/400 4.1. Changes in File declaration 4.1.1. Renaming a record format name of externally described file 4.1.2. Renaming a field name 4.1.3. Ignoring record format names in logical file 4.1.4. Declaring overflow indicator 4.1.5. Decalring a subfile 4.2. Record Locking and Relative-Record-Number processing 4.3. Using Commitment Control AS/400-RPGLE-SN-2.0 Page No. 1 ILE RPG/400 5. Data structures 5.1. Uses of Data structure 5.1.1. Divide a field into subfield 5.1.2. Group fields 5.1.3. Define externally described data structure 5.1.4. Define data area data structure 5.1.5. Define multiple occurance data structure 5.2. Program-described and Externally-described data structure 5.3. Special data structures 5.3.1. Data area data structure 5.3.2. File inforamtion data structure 5.3.3. Program-status data structure 6. Arrays and Table processing 6.1. Differences between Arrays and Tables 6.2. Arrays 6.2.1. Prerun-time arrays 6.2.2. Compile-time arrays 6.2.3. Run-time arrays 6.3. Searching Arrays 6.3.1. Searching an Array without an Index 6.3.2. Searching an Array with an Index 6.4. Sorting an Array 6.5. How Tables differs from Array in coding 7. Pointers 7.1. Understanding pointers 7.2. Declaring a pointer data type 7.3. Dynamic memory allocation 7.4. Pointers to functions 8. Exception and Error handling 8.1. Difference between OPM and ILE RPG/400 Exception handling 8.2. Using RPG-Specific Handlers 8.2.1.Specifying error indicators 8.2.2.Using a File Error ( INFSR ) subroutine 8.2.3 Using a Program Error Subroutine 9. Built-in functions AS/400-RPGLE-SN-2.0 Page No. 2 ILE RPG/400 1. INTRODUCTION TO ILE 1.1. What is ILE? ILE is a set of tools and associated system support designed to enhance program development on the AS/400 system. These capabilities can be exploited by programs produced by the new ILE family of compilers which includes ILE C/400 , ILE RPG/400, ILE COBOL/400, ILE CL. 1.2. Advantages of ILE 1. Binding: Binding the modules together speeds up the call. The ILE call method is referred to as a static or bound procedure call. The binding capability makes it far more practical to develop applications in a highly modular fashion. 2. Modularity: 3. Coexistence with Existing Applications: ILE programs can call OPM programs and other ILE programs. Similarly , OPM programs can call ILE programs and other OPM programs. 4. Source Debugger: The source debugger allows to debug the ILE programs and service programs. 5. Better control over resources: Under ILE, a resource can be scoped to any of the following 1. Faster compile time 2. Simplified maintenance 3. Simplified testing 4. Better use of programming resources 5. Easier migrating of code from other platforms a) A Program b) An activation group c) The Job Shared Open data paths (ODPs) are an example of resources you can better control with ILE’s new level of scoping. The ability to scope a shared open data path (ODP) to the application is useful in the area of commitment control. 6. Better Code Optimization: The ILE translator does many more types of optimization than the Original Program Model (OPM) does. 7. Better environment for C: C has become the language of choice for tool builders. Because of this, a better C language means that more and more of the latest application development tools are migrated to the AS/400. 8. Foundation for the future: As we move into object-oriented programming languages and visual programming tools, the need for ILE becomes even more apparent. 1.3 History of ILE The programming environment provided when the AS/400 system was introduced is called the original program model (OPM).In version 1 Release 2, the Extended program model(EPM) was introduced. Then the ILE is introduced. The major factors of each programming model is listed below: AS/400-RPGLE-SN-2.0 Page No. 3 ILE RPG/400 1.3.1 OPM: 1. Dynamic program call (Simplicity) 2. Single entry point 3. Language controls run-time behavior 4. One Compilation = One program 5. Variables visible across entire program 6. Resources shared across a job 1.3.2 EPM: 1. Multiple entry points 2. Nested scoping of variables 3. Automatic and static variables 4. External data shared across programs 5. Separate address space 6. Concept of “environment” 7. Optimal for development tools, OS code, Scientific. 1.3.3. ILE: 1. 2. 3. 4. 5. 6. Dynamic or static binding Significant new language function(especially RPG) One environment integrates all ILE languages Improved performance for C applications Environment provides run-time behavior OPM and EPM still available 1.4 ILE Concepts 1.4.1. Procedures Procedure is a executable code with an entry point. Called with new CALL BOUND PROCEDURE syntax. Procedures appear on call stack. 3. In ILE RPG/400, even main source is also a procedure. 1. 2. 1.4.2. Module 1. 2. 3. 4. 5. 6. 7. 8. 9. Output from an ILE compiler Basic building block for ILE runnable objects May have a Program Entry Procedure (PEP) defined If a PEP is defined, a User Entry Procedure (UEP) is also defined. Is not a runnable object. May Export procedure and data item names May import procedure and data item names May have a debug data defined The object is represented as *MODULE To create a module in ILE RPG/400, Use the following command: CRTRPGMOD MODULE(Name) SRCFILE(Srcfilename) SRCMBR(Member) AS/400-RPGLE-SN-2.0 Page No. 4 ILE RPG/400 Example of a module and a procedure in ILE RPG/400: *************** Beginning of data ************************************* 0000.01 * This module does not have a main procedure. This module contains 0000.02 * two procedures display and mult. 0001.00 Hnomain 0001.01 *Protype definition 0001.02 *display take msg parameter of lenght 20 and it does not return any. 0002.01 Ddisplay pr 0003.00 D msg 20a 0003.01 *Mult takes two parameters a and b. It results a value of length 10. 0003.02 Dmult pr 10 0 0003.03 D a 5 0 0003.04 D b 5 0 0003.05 *Procedure definition of display 0004.00 Pdisplay b 0005.00 Ddisplay pi 0006.00 D msg 20a 0007.00 C 'hello world' dsply 0008.00 Pdisplay e 0009.00 *Procedure definition of mult 0010.00 Pmult b 0011.00 Dmult pi 10 0 0012.00 D a 5 0 0013.00 D b 5 0 0014.00 C return a * b 0015.00 Pmult e ****************** End of data **************************************** We can also create modules with main source. Then there is no need to include NOMAIN keyword on the control specification. 1.4.3. ILE Program 1. 2. 3. 4. 5. 6. 7. One or more modules from any ILE language are copied to make the *PGM object You can control over which modules PEP becomes the one and only PEP for the program On a dynamic program call, the module’s PEP that was selected as the PEP for the program gets control to run. procedures and data item names cannot be exported from the program Procedures or data item names can be imported from other ILE objects A program is a runnable object The object is represented as *PGM After creating one or two modules, you can create a program object by using CRTPGM command. In that command we have to list all the modules which we want to include in that program. 1.4.4. ILE Service Program 1. A service program is a bound program consisting of a set of procedures that can be called by procedures in other bound programs. 2. No PEP is associated with the service program.. Because there is no PEP, a dynamic call to a service program is not valid. 3. Signatures are generated from the procedure and data item names that are exported from the service program. The set of exports contained in a service program are the interface to the services provided by it. AS/400-RPGLE-SN-2.0 Page No. 5 ILE RPG/400 4. When you bind a service program to a program, the contents of service program are not copied into the bound program. Instead, linkage information of the service program is bound into the program. 5. The object is represented as *SRVPGM After creating modules required for service program, you can create service program with the CRTSRVPGM command. For example, assume you want to create a service program which contains modules MOD1, MOD2. Then you can use the following command. CRTSRVPGM SRVPGM(service program name) MODULE(modules created for service program) EXPORT(*all). In keyword EXPORT, *all is required to give access to all procedures in modules MOD1 and MOD2. If you don’t want to give the user access to all procedures in MOD1 and MOD2, you can control that with the use of binding language. Basically we create service programs to put all our reusable procedures. If any program requires the procedures in service program, while creating that program using CRTPGM include the name of the service program in the parameter value of BNDSRVPGM, and make a simple call to that procedure from your program. There is no need to write the entire procedure next in the program. 1.4.5. Binding Directory 1. Contains the names of modules and service programs that you may need when creating an ILE program or service program. 2. Is a system object , identified by the symbol *BNDDIR 3. Binding directory entries do not have to exist yet on the system. 4. The named objects are used only if any unresolved imports exist and if the named objects provides an export to satisfy the unresolved import request. 1.4.6. Activation 1. Is a process used to prepare an ILE program to run. 2. Allocates and initializes static storage for an ILE program 3. Completes the binding of ILE programs to ILE service programs 1.4.7. Activation Group 1. A substructure of a job in which all ILE programs and service programs are activated 2. Scope resources to the ILE programs 3. Change the symbolic links to used ILE service programs to physical addresses. 4. Ensures that ILE programs running the same job run independently without intruding on each other by scoping resources to the activation group AS/400-RPGLE-SN-2.0 Page No. 6 ILE RPG/400 2. INTRODUCTION TO ILE RPG/400 PROGRAMMING This chapter presents a high-level overview of the RPGIV programming language that distinguish RPG from other programming languages. You should be familiar and comfortable with all of these features before you program in RPGIV language. This part provides information on the following topics that you should know: 2.1. RPGIV specifications 2.2. Cycle programming 2.3. Example of an ILE RPGIV program 2.4.1. ILE Improvements over OPM to RPGIV users 2.4.1. Program creation (Compilation) 2.4.1.1. Create a program usign CRTBNDRPG to maximize OPM compatibility 2.4.1.2. Create an ILE program using CRTBNDRPG 2.4.1.3. Create an ILE program using CRTRPGMOD and CRTPGM 2.4.1.4. Compiler listin 2.4.2. Program management 2.4.3. Program call (Execution) 2.4.3.1. Parameter passing syle 2.4.4. Source debugging 2.4.5. Bindable application program interface(APIs) 2.5. Data types 2.1. RPGIV SPECIFICATIONS: Writing ILE RPG/400 programs requires a knowledge of the specification forms. Many of the entries which make up a specification type are position-dependent. There are seven types of RPGIV specifications. Each specification type is optional. In RPGIV, procedures can be written after main source. Specifications must be entered into your source program in the order shown below. Main source section: 1. 2. 3. 4. 5. 6. Control specifictions(H) provide the compiler with information about generating and running programs, such as the date format, debugging, and use of alternate collating sequence or file translation. File description specifications(F) describe all the files that your program uses. Definition specifications(D) describe the data(datastructures, arrays, tables) used by program. Input specifications(I) describe the input records and fields used by the program. Calculation specifications( C) describe the calculations done on the data and the order of calculations. Output specifications(O) describe the output records and fields used by the program. Subprocedure section: Procedure specifications(P) mark the beginning and end of the Subprocedure, indicate the Subprocedure name, and whether it is exported. 2. Definition specifications(D) describe the local data used by the Subprocedure. 3. Calculation specifications( C) describe the calculations done on both the global and local data and the order of calculations. 1. 2.2 CYCLE PROGRAMMING: AS/400-RPGLE-SN-2.0 Page No. 7 ILE RPG/400 The program cycle is a series of steps that your program repeats until an end-of-file condition is reached. When you let the compiler provide the logic for your programs, it is called Cycle programming. No cycle code is generated for subprocedures or when NOMAIN is specified on the control specification. RPG program logic cycle Following explains the logic cycle briefly: 1. 2. 3. 4. 5. 6. 7. RPG processes all heading and detail lines ( H or D in position 17 of the output specifications). RPG reads the next record and sets on the record identifying and control level indicators. RPG processes total calculations ( conditioned by control level indicators L1 through L9, an LR indicator, or an L0 entry). RPG processes all total output lines( identified by a T in position 17 of the output specifications). RPG determines if the LR indicator is on. If it is on, the program ends. The fields of the selected input records move from the record to a processing area. RPG sets on field indicators. RPG processes all detail calculations ( not conditioned by control level indicators in positions 7 and 8 of the calculation specifications). Go back to step1. The first and last time through the program cycle differ somewhat from other cycles. There is no cycle code generated for a Subprocedure. 2.3 EXAMPLE OF AN ILERPGIV PROGRAM: The following program covers the concepts of cycle, Subprocedure and static binding. The logic flow of program(TAXC) is given below: For each record in EMPMSTR Calculate Tax depending on salary. If Tax > 0 Then Print Employee name and Tax computed in printer file. The DDS for EMPMSTR is as follows: *************** Beginning of data ************************************* 0001.00 0002.00 0003.00 0004.00 A A A A R EMPMSTRA ENO 5 0 ENAME 15A ESAL 10 2 ****************** End of data **************************************** AS/400-RPGLE-SN-2.0 Page No. 8 ILE RPG/400 The ILE RPG code for above requirement is as follows: *************** Beginning of data ************************************* 0001.00 Fempmstr ip e disk 0002.0 0 Fqsysprt o f 80 printer 0003.00 *Declaring a stand alone field(temporary) with length 8 and decimal positions 2 0004.00 Dtax s 8p 2 0005.00 *Declaring a constant 0006.00 DHeading c 'Name 0007.00 *Declaring a prototype for procedure 0008.00 Dcalctax pr 8p 2 0009.00 D esal 10p 2 0010.00 *Calling a procedure(Protyped call) 0011.00 C eval tax = calctax(esal) 0012.00 Oqsysprt H 1P 0013.00 O 60 HEADING 0014.00 O D 0015.00 O ENAME 20 0016.00 O TAX 40 '$ 0. ' 0017.00 *Declaring a prototype interface 0018.00 Pcalctax b 0019.00 Dcalctax pi 8p 2 0020.00 D esal 10 2 0021.00 C if esal > 10000 0022.00 C return esal * (25/100) 0023.00 C else 0024.00 C return 0 0025.00 C endif 0026.00 Pcalctax e Tax ' ****************** End of data **************************************** 2.4. ILE IMPROVEMENTS OVER OPM TO RPGIV USERS Compared to OPM, ILE provides RPG users with improvements or enhancements in the following areas of application development: Program creation (Compilation) 2.4.1.1. Create a program usign CRTBNDRPG to maximize OPM compatibility 2.4.1.2. Create an ILE program using CRTBNDRPG 2.4.1.3. Create an ILE program using CRTRPGMOD and CRTPGM 2.4.1.4. Compiler listing 2.4.2. Program management 2.4.3. Program call (Execution) 2.4.3.1. Parameter passing style 2.4.4. Source debugging 2.4.5. Bindable application program interface(APIs) 2.4.1. 2.4.1 Program creation strategies(Compiltaion): 1. 2. 3. Create a program using CRTBNDRPG to maximize OPM compatibility. Create an ILE program using CRTBNDRPG Create an ILE program using CRTRPGMOD and CRTPGM. AS/400-RPGLE-SN-2.0 Page No. 9 ILE RPG/400 2.4.1.1. Create a program using CRTBNDRPG to maximize OPM compatibility: This is used to create ILE program that interact well with OPM programs. You may want such a program temporarily while you complete your migration to ILE. In this method, Create a program object using the CRTBNDRPG command, specifying DFTACTGRP(*YES). ] Specifying DFTACTGRP(*YES) means that the program object will run only in the default activation group.(The default activation group is the activation group where all OPM programs are run.) When you use this approach you can’t make use of ILE static binding. For example, you can’t make use of some Bindable APIs. 2.4.1.2. Create an ILE program using CRTBNDRPG: By using this method, ILE program can take advantage of ILE static binding. You can also specify the activation group in which the program will run. In this method, Create a program object using the CRTBNDRPG command, specifying DFTACTGRP(*NO). The main drawback of this method is you do not have a permanent module object that you can later reuse to bind with other modules to create an ILE program. Further more, any procedure calls must be to modules to service programs that are identified in a binding directory. If you want to bind two or more modules without using a binding directory you need to use the third strategy. 2.4.1.3. Create an ILE program using CRTRPGMOD and CRTRPG: The two-step process of program creation consists of compiling source into modules using CRTRPGMOD and then binding one or more module objects into a program using CRTPGM. This strategy allows you to fully utilize the concepts offered by ILE. With this strategy, you can create permanent modules, modularize an application. There is no need to compile the entire application if one module changes. 2.4.1.4 Compiler listing consists minimally following sections: prologue ( command option summary) Source listing, which includes: In-line diagnostic messages Match-field table Additional diagnostic messages Field positions in output buffer /COPY member table Compile time data which includes: Alternate collating sequence records and table or NLSS information and table File translation records Array records Table records Message summary Final summary Code generation report(appears only if there are errors) Binding report(applies only to CRTBMDRPG; appears only if there are errors) 2.4.2. Program Management: Earlier program management is done at job level ie., you can scope file overrides and shared open data paths and commitment-control operations at job level. Now for better control of resources, concept of activation group came into picture. In one job, there can be any number of activation groups. Now you can scope file overrides, open data paths and commitment-control at activation group level. AS/400-RPGLE-SN-2.0 Page No. 10 ILE RPG/400 The process of getting a program or service program ready to run is known as activation. Activation allocates resources within a job so that one or more programs can run in that space. An activation group is a substructure of a job and consists of system resources that are allocated to run on or more ILE or OPM programs. A named activation group allows you to manage a collection of ILE programs and service programs as one application. An activation group is the key element governing an ILE application’s resources and behavior. 2.4.3 Program call: Dynamic call: The called program’s name is resolved to an address at run time, just before the calling program passes control to the called program. In ILE, you can write applications in which ILE RPG/400 programs and OPM RPG/400 programs continue to interrelate through the traditional use of dynamic program calls. Static call: Static calls involve calls between procedures. A procedure is a self-contained set of code that performs a task and then returns to the caller. Because the procedure names are resolved at bind time(that is, when you create the program), static calls are faster than dynamic calls. 2.4.3.1. Parameter passing style: ILE RPG/400 allows three methods for passing and receiving prototyped parameters: By reference By value By read-only reference By reference: This is default parameter passing style for ILE RPGIV. You should pass parameters by reference to a procedure when you expect the call to modify the field passed. You may also want to pass by reference to improve run-time performance. Example Have a look at the following program. *************** Beginning of data ************************************* 0001.00 Dpref pr 0002.00 D temp 5 0 0003.00 *Initializing variable temp. 0004.00 Dtemp s 5 0 inz(100) 0006.00 *Display variable temp first time 0007.00 C temp dsply 0008.00 *Calling a procedure with callp because no return value. 0009.00 C callp pref(temp) 0010.00 *Display variable temp third time 0011.00 C temp dsply 0012.00 C seton lr 0013.00 Ppref b 0014.00 Dpref pi 0015.00 D temp 5 0 0016.00 *Modifying value in procedure 0017.00 C z-add 10 temp 0018.00 *Display variable temp second time AS/400-RPGLE-SN-2.0 Page No. 11 ILE RPG/400 0019.00 C temp dsply 0020.00 Ppref e ****************** End of data **************************************** The output of the program is 100, 10 and 10 respectively. This is because in CALLP statement, the address of variable TEMP is being passed to PREF Subprocedure. So modifications to TEMP are not lost. By Value: When a parameter is passed by value, the compiler passes the actual value to the called procedure. To pass a parameter by value, specify the keyword VALUE on the parameter definition in the prototype. Example: Observe the changes made in the above program. *************** Beginning of data ************************************* 0001.00 Dpref pr 0002.00 D temp 5 0 Value 0003.00 *Initializing variable temp. 0004.00 Dtemp s 5 0 inz(100) 0005.00 *Initializing variable temp. 0006.00 *Display variable temp first time 0007.00 C temp dsply 0008.00 *Calling a procedure with callp because no return value. 0009.00 C callp pref(temp) 0010.00 *Display variable temp third time 0011.00 C temp dsply 0012.00 C seton lr 0013.00 Ppref b 0014.00 Dpref pi 0015.00 D temp 5 0 Value 0016.00 *Modifying value in procedure 0017.00 C z-add 10 temp 0018.00 *Display variable temp third time 0019.00 C temp dsply 0020.00 Ppref e ****************** End of data **************************************** The output of the program is 100, 10 and 100 respectively. This is because, on CALLP statement, the value of temp is being passed, not it’s address. So modifications to temp in Subprocedure are not remained. By Read-only reference: Passing by read-only reference is useful if you must pass the parameter by reference and you know that the value of the parameter will not be changed during the call. For example, many system APIs have read-only parameters specifying formats, or lengths. To pass a parameter by read-only reference, specify the keyword CONST on the definition specification of the parameter definition in the prototype. Example: Dpassror D Num PR 10I 0 CONST 2.4.4. Source debugging: The ILE source debugger is used to detect errors in and eliminate errors from program objects and service programs. Debug data is created depending on DBGVIEW parameter on CRTBNDPGM or AS/400-RPGLE-SN-2.0 Page No. 12 ILE RPG/400 CRTRPGMOD. A program or module must have debug data available if you are to debug it. The following values for DBGVIEW parameter are valid: AS/400-RPGLE-SN-2.0 Page No. 13 ILE RPG/400 *None : *STMT : *SOURCE: *COPY : *LIST : No debug data is created You have to make use of statement numbers. Source will not be displayed. It is default value. Contains text from the root source member. We generally use this option. Contains text form the root source member and all copy members. Contains text in compiler listing. To debug a program, Compile it with required DBGVIEW parameter value. Set the break point using DSPMODSRC. Then Call the program. The debugger allows stepinto, step over functions. 2.4.5. Bindable APIs: ILE offers a number of bindable APIs that can be used to supplement the function currently offered by ILERPG/400. The bindable APIs provide program calling and activation capability, condition and storage management, math functions, and dynamic screen management. To use these bindable APIs, Compile the programs using DFTACTGRP(*NO). Examples: CEECRHP - To create your own heap CEEFRST - Free storage in your own heap CEE4ABN - Abnormal End etc., 2.5 Data types: Different datatypes allowed in ILE RPGIV are as follows: A - Character field B - Fixed binary field D - Date field F - Floating-point field G - Graphic character field I - Signed Integer field P - Packed decimal field S - Zoned field T - Time field U - Unsigned Integer field Z - Timestamp field *-Pointer field Different date formats allowed are *MDY, *DMY, *YMD, *JUL, *ISO(yyyy-mm-dd), *USA(mm/dd/yyyy), *EUR(dd.mm.yyyy) and *JIS(yyyy-mm-dd). AS/400-RPGLE-SN-2.0 Page No. 14 ILE RPG/400 3. OP-CODE VARIATIONS IN ILERPG/400 OVER RPG/400 You feel familiar in many places of ILERPG/400 because many op-codes in RPG/400 are intact. There are some additional opcodes which need attention. In some existing opcodes, slight modifications are incorporated for better performance. This chapter does not explains in detail those operations which are in RPG/400. This chapter briefly explains the additional op-codes and modifications of existing op-codes in the following categories of operations: 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 Arithmetic operations Branching operations Call operations Date operations Moving Date-Time data Operations using Expressions Message operation String operations Structured programming operations 3.1. ARITHMETIC OPERATIONS: The arithmetci operations are: ADD (H), DIV (H), MULT (H), MVR, SQRT (H), SUB (H), XFOOT(H), Z-ADD (H), Z-SUB(H). You can observe the modification in arithmetic operations, ie., the symbol (H). H means Half adjust ie., round the numeric result. In RPG/400, we give this H in 53 column of C-spec. 3.2. BRANCHING OPERATIONS: CABxx, GOTO, ITER, LEAVE, TAG. We haven’t gone in detail to explain above operations as you are already be familiar with them. The ITER operation transfers control from within a DO-group to the ENDDO statement of the DO-group. The LEAVE operation is similar to the ITER operation; however, LEAVE transfers control to the statement following the ENDDO operation. 3.3. CALL OPERATIONS: The CALL operations are: CALL, CALLB, CALLP, PARM, PLIST, RETURN. A prototype is an external definition of the call interface that allows the compiler to check the interface at compile time. In ILE, it is possible to call either program or procedure. Furthermore, ILE RPG/400 provides the ability to call prototyped or non-prototyped programs and procedures. There are three types of calls: Program call, Procedure call and in expressions A Program call is a call that is made to a program object(*PGM). The called program’s name is resolved to an address at runtime, just before the calling program passes control to the called program for the first time. For this reason, program calls are often referred to as dynamic calls. You can use CALLP operation or both the CALL and PARM operation to make a program call. Use CALLP if you have prototype for called program in calling program otherwise use CALL. If you use CALL, then the compiler cannot perform type checking on the parameters, which may result in run-time errors. In procedure call, the called procedure’s name is resolved to an address at compile time. Procedure calls are also referred to bound calls. These calls are faster than program calls. You use the CALLP or both the CALLB and PARM operation to make a procedure call. Use CALLP if you have prototype for that called procedure otherwise use CALLB. If you use the AS/400-RPGLE-SN-2.0 Page No. 15 ILE RPG/400 CALLB, then the compiler cannot perform type checking on the parameters, which may result in run-time errors. You can also call a prototyped procedure with an expression if the procedure returns a value. Example: The following program accepts a valid employee code from screen and displays the detail employee designation. For example, if you give SE, ‘Software Engineer’ will be displayed. *************** Beginning of data ************************************* 0001.00 Ddesc s 20a 0002.00 *Prototype 0003.00 Dempdesc pr 20a 0004.00 D des 3a 0005.00 *To accept designation code from workstation 0006.00 C 'Desig?:' dsply desig 3 0007.00 *Calling a prototyped procedure in expression. If this function does 0008.00 * not return any value you can use CALLP. 0009.00 C eval desc = empdesc(desig) 0010.00 C desc dsply 0011.00 C seton lr 0012.00 PEMPDESC B 0013.00 *Procedure interface 0014.00 DEMPDESC PI 20A 0015.00 D DES 3A 0016.00 C SELECT 0017.00 C WHEN DES = 'SE' 0018.00 C RETURN 'SOFTWARE ENGINEER' 0019.00 C WHEN DES = 'SSE' 0020.00 C RETURN 'SENIOR S. ENGINEER' 0021.00 C WHEN DES = 'GM' 0022.00 C RETURN 'GENERAL MANAGER' 0023.00 C OTHER 0024.00 C RETURN 'NOT VALID' 0025.00 C ENDSL 0026.00 PEMPDESC E ****************** End of data **************************************** 3.4. DATE OPERATIONS: Date operations allow you to perform date and time arithmetic, extract portions of a date, time or timestamp field; or test for valid fields. They operate on Date, Time and Timestamp fields, and character and numeric fields representing dates, times and timestamps. The data operations are: ADDDUR(Add Duration): The ADDDUR operation adds the duration specified in factor 2 to a date or time and places the resulting date, time or timestamp in the result field. Example: D Duedate S D DATFMT(*MDY) INZ(D’12 31 92’) *To determine the date 23 days later C ADDDUR 23:*D DUEDATE *To subtract 30 days from a duedate C ADDDUR -30:*D DUEDATE AS/400-RPGLE-SN-2.0 Page No. 16 ILE RPG/400 The valid duration codes(and their short forms) are: *YEARS for the year (*Y) *MONTHS for the month (*M) *DAYS for the day (*D) *HOURS for the hours (*H) *MINUTES for the minutes (*MN) *SECONDS for the seconds (*S) *MSECONDS for the microseconds (*MS) EXTRACT(Extract Date/Time/Timestamp): The EXTRACT operation code will return one of the year, month or day part of a date or timestamp field the hours, minutes or seconds part of a time or timestamp field the microseconds part of the timestamp field to the field specified in the result field. Example: EXTRACT Duedate:*M Month 2 0 It extracts the Month and places it in variable Month. SUBDUR(Subtract Duration): The SUBDUR operation has been provided to: Subtract a duration to establish a new date, time, or timestamp Calculate a duration Example: *Adds 30 days to a due date C SUBDUR -30:*D Duedate *Calculate the number of days between a LOANDATE and a DUEDATE C Loandate SUBDUR Duedate Days:*D 5 0 TEST(Test Date/Time/Timestamp): The TEST operation code allows users to test the validity of date, time, or timestamp fields prior to using them. Example: D Datefield S D DATFMT(*JIS) D Date1 S 6P 0 INZ(910921) C *DMY TEST (D) Date1 *Indicator 20 is set since Date1 is not in *DMY format. *(D) indicates Date1 is a date field. 20 C TEST Datefield 21 *No factor1 since result is a D data type field. Ind 21 will not be set on since the field contains a valid date. 3.5. MOVING DATE-TIME DATA: The MOVE and MOVEL operation codes can be used to move date, time and timestamp data type fields. Factor 1 is optional for MOVE and MOVEL and is used to specify the format of the character or numeric field. Any valid format may be specified. If factor 1 is blank, the format of the DateTime field is used. Factor 2 is required and may contain a character or numeric, date, time or timestamp field to be converted. The date or time is placed in the result field according to its defined format or the format code specified in factor 1. AS/400-RPGLE-SN-2.0 Page No. 17 ILE RPG/400 Example: The following example accepts the birth date from the workstation and displays his age interms of year. *************** Beginning of data ************************************* 0001.00 Dcurdate s d 0002.00 Dbd s d 0003.00 Dbirthd s 10 0004.00 Dyears s 3 0 0005.00 *Enter the date in *ISO format(yyyy-mm-dd) 0006.00 C 'b.date?' dsply birthd 0007.00 *Convert from date format to date field. 0008.00 C *iso move birthd bd 0009.00 *Current date 0010.00 C *dmy movel udate curdate 0011.00 *Calculating the years. 0012.00 C curdate subdur bd years:*y 0013.00 C years dsply 0014.00 C seton lr ****************** End of data **************************************** 3.6. OPERATING USING EXPRESSIONS: Using expressions in operations is an improvement in ILE RPG/400 over RPG/400. The operations using expressions are as follows: EVAL, DOU, DOW, IF, WHEN. We are already familiar with above operations except EVAL. EVAL: The EVAL operation code evaluates an assignment statement of the form result = expression. The expression is evaluated and the result placed in result. Example: Assume A = 10; B = 9; C = 8; D = 7 EVAL RESULT = A + B + (C - D) The value of RESULT after the operation is 20. Assume A = ‘Wipro Technologies’ EVAL %SUBST(A:7:12) = ‘Limited’ The value of A is ‘Wipro Limited’ 3.7. MESSAGE OPERATION: The message operation DSPLY allows interactive communication between the program and the operator or between the program and the display workstation that requested the program. The Factor 1 contains either field name to display value or “message” to display. The result field contains the reply. 3.8. STRING OPERATIONS: The string operations include concatenation, scanning, substringing, translation, and verification. String operations can only be used on character or graphic fields. The string operations are: CAT (P), CHECK, CHECKR, SCAN, SUBST (P), XLATE (P) The only difference in these operations from RPG/400 is the symbol (P). The symbol ‘P’ means pad the result with blanks or zeros. In RPG/400 we give P in 53 column of string operations. AS/400-RPGLE-SN-2.0 Page No. 18 ILE RPG/400 STRUCTURED PROGRAMMING OPERATIONS: There is no difference in structured operations. The structured operations are as follows: DO, DOUxx, DOWxx, ELSE, END, Ifxx, ITER, LEAVE, Orxx, OTHER, SELECT, WHENxx where xx can be GT, LT, EQ, NE, GE, LE. AS/400-RPGLE-SN-2.0 Page No. 19 ILE RPG/400 4. FILE HANDLING IN ILE RPG/400 The key element for all I/O operations on the AS/400 is the file. The system supports the following file types: Database files allow storage of data permanently on system. Device files allow access to externally-attached devices. Includes display files, printer files, tape files, diskette files and ICF files. Save files used to store saved data on disk. DDM files allow access to datafiles stored on remote systems. When identifying the file description your program will be using, you must indicate whether it is a program-described file or an externally described file. Externally described files offer the following advantages over program-described files: Less coding in programs Less maintenance activity when the file’s record format is changed. Improved documentation Improved reliability The commonly used file operation codes used in ILE RPG/400 are CHAIN (N), CLOSE, COMMIT, DELETE, EXCEPT, EXFMT, OPEN, READ (N), READC, READE (N), READP (N), READPE (N), ROLBK, SETGT, SETLL, UNLOCK, UPDATE, WRITE. The only difference is operation extender (N). If you specify N as the operation extender for an update disk file, a record is read without locking. If no operation extender is specified, the record is locked if the file is an update disk file. We are not explaining all the above operations in detail as all are familiar to you. Changes has been incorporated in the declaration of file(In F-spec). For example to rename a record, declaring a subfile etc., This chapter explains the changes incorporated in ILERPG/400. This chapter explains the following topics in brief: 4.1. Changes in File declaration 4.1.1. Renaming a record format name of externally described file 4.1.2. Renaming a field name 4.1.3. Ignoring record format names in logical file 4.1.4. Declaring overflow indicator 4.1.5. Decalring a subfile 4.2. Record Locking and Relative-Record-Number processing 4.3. Using Commitment Control 4.1. CHANGES IN FILE DESCRIPTION: 4.1.1. Renaming Record-Format Name: To rename a record-format name, use the RENAME keyword on the file description specifications for the externally described file. Example: To rename a record format name REC1 in FILEA, use the following FFILEA IP E K DISK RENAME(REC1:NewRecordName) 4.1.2. Renaming Field Names: AS/400-RPGLE-SN-2.0 Page No. 20 ILE RPG/400 You can partially rename all fields in an externally described file by using the PREFIX keyword on the file description specification for the file. Example: To add the prefix WTH to each field in file FILEA, use the following FFILEA IP E K DISK PREFIX(WTH) You can rename a field using I spec. Example: Assume the file FILEA contains REC1 which inturn contains field FLD1. Assign a record-identifying indicator to FILEA and rename the field FLD1 to FIELD1. IREC1 01 I FLD1 FIELD1 *FLD1 is external field name and FIELD1 is name used in program. 4.1.3. Ignoring record formats: If a record format in an externally described file is not to be used in a program, you can use the IGNORE keyword to make the program run as if the record format didnot exist in the file. For logical files, this means that all data associated with that format is inaccessible to the program. Alternatively, the INCLUDE keyword can be used to include only those record format names that are to be used in the program. All other record formats contained in the file will be excluded. Example: Assume the file FILEA contains the following record formats: REC1, REC2, REC3, REC4. To make the program run as if only the REC1, REC2 records existed, either of the following two methods can be used: FFILEA or FFILEA UF E K DISK IGNORE(REC3:REC4) UF E K DISK INCLUDE(REC1:REC2) 4.1.4. Declaring Overflow indicator: Type an indicator in keyword OFLIND to set on when a line is printed on the overflow line, or when a overflow line is reached or passed during a space or skip operation. Example:Decalring indicator 40 as overflow indicator. FQSYPRT O 4.1.5. F 80 PRINTER OFLIND(*IN40) Declaring a subfile: Processing subfiles in ILE RPGIV is same as RPG/400. The only difference lies in declaring a subfile and relative record number in file description specification. Example: To declare a subfile named SUBFILE with relative reocrd number RECNUM, Fdisplayfile CF E WORKSTN SFILE(SUBFILE : RECNUM) 4.2. RECORD LOCKING AND RELATIVE RECORD NUMBER PROCESSING: 4.2.1. RECORD LOCKING When record is read by a program, it is read in one of two methods: input or update. If a program needs a record for update, a lock is placed on that record. Another program cannot read the same record for update until the first program releases that lock. If a program needs a record for input, no lock is placed on the record. For update files, you can specify that a record be read for input by using one of the input operations CHAIN, READ, READE, READP, READPE and specifying an oepration code extender(N) in the operation code fied following the operation code name. AS/400-RPGLE-SN-2.0 Page No. 21 ILE RPG/400 When a record is locked by an RPG IV program, that lock remains until one of the following occurs: the record is updated the record is deleted another record is read from file a SETLL or SETGT operation is performed against the file an UNLOCK operation is performed against the file an outpu operation defined by an output specification with no field names included is performed against the file. 4.2.2. Relative-Record-Number Processing: Use the RECNO keyword on a file description specifications to specify a numeric field that contains the relative record number. A RECNO field must be specified if new records are to be placed in the file by using the output specification or a WRITE operation. When you update or add a record to a file by relative record number, the record must already have a place in the member. For an update, that place must be a valid existing record; for a new record, that place must be a deleted record. The current relatvie record number is placed in the RECNO field for all retrieval operations or operations that reposition the file( for example, SETLL, CHAIN, READ). Example: The logical order of the following program is as follows -Read a first record -Delete that record -Write another record in the place of first record not at the end of file. -Until EOF of EMPMSTR, read the file and observe the change in RECNO field. The DDS for the file EMPMSTR is as follows *************** Beginning of data ************************************* 0001.00 A R EMPMSTRA 0002.00 A ENO 5 0 0003.00 A ENAME 15A 0004.00 A ESAL 10 0 ****************** End of data **************************************** The RPG IV code is as follows: *************** Beginning of data ************************************* 0001.00 *Declare a file with relative record number field 0002.00 Fempmstr uf a e disk recno(trrn) 0003.00 Dtrrn s 3 0 0004.00 *Read the first record in EMPMSTR file 0005.00 C read empmstr 30 0006.00 *Delete the first record in file 0007.00 C delete empmstr 0008.00 *Write another record in the place of first record, not at last. 0009.00 C z-add 1 trrn 0010.00 C z-add 100 eno 0011.00 C move 'example' ename 0012.00 C z-add 1000000 esal 0013.00 C write empmstra 0014.00 *Until End of file, read the file and display Relative record number. 0015.00 C dow not *in30 0016.00 C read empmstr 30 AS/400-RPGLE-SN-2.0 Page No. 22 ILE RPG/400 0017.00 C trrn dsply 0018.00 C enddo 0019.00 C seton lr ****************** End of data **************************************** 4.3. USING COMMITMENT CONTROL: Commitment control is used to process file operations as a group. With commitment control, you ensure one of two outcomes for the file operations: All of the file operations are successful ( a commit operation) None of the file operations has any effect ( a rollback operation) To use the commitment control, you do the following: On the AS/400: 1. 2. To use commitment control, create journal, journal receiver and start the journal physical file. Notify the AS/400 when to strart and end commitment control: Use STRCMTCTL and ENDCMTCTL In the RPG program: Specify commitment control (COMMIT) on the file-description specifications of the files you want under commitment control. 2. Use the COMMIT ( commit ) operation code to apply a group of changes to files under commitment control, or use ROLBK ( Roll Back ) operation code to eliminate the pending group of changes to fiels under commitment control. 1. The COMMIT oepration tells the system that you have completed a group of changes to the files under commitment control. The ROLBK operation eliminates the current group of changes to the files under commitment control. Example: This example illustrates the specifications and CL commands required for a program to operate under commitment control. To prepare for using commitment control, you issue the following CL commands: 1. 2. 3. CRTJRNRCV JRNRCV(RECEIVER) CRTJRN JRN(JOURNAL) JRNRCV(RECEIVER) STRJRNPF FILE(FILEA) JRN(JOURNAL) In RPG IV program, FFILEA UF E K DISK COMMIT *After a group of database operations, if you want to commit all those operations C COMMIT *If you want to revert all the database operations done on FILEA. C ROLBK To operate your program under commitment control, you issue the following commands: 1. 2. STRCMTCTL CALL RPGIVprogram AS/400-RPGLE-SN-2.0 Page No. 23 ILE RPG/400 3. ENDCMTCTL AS/400-RPGLE-SN-2.0 Page No. 24 ILE RPG/400 5. DATA STRUCTURES Data structure define an area in storage and the layout of related subfields. You define a data structure by specifying DS in positions 24 thourgh 25 on a definition specification. This chapter briefly explains the following: 5.1. Uses of Data structure 5.1.1. Divide a field into subfield 5.1.2. Group fields 5.1.3. Define externally described data structure 5.1.4. Define data area data structure 5.1.5. Define multiple occurance data structure 5.2. Program-described and Externally-described data structure 5.3. Special data structures 5.3.1. Data area data structure 5.3.2. File inforamtion data structure 5.3.3. Program-status data structure 5.1. Data structures may be used to: 5.1.1. Divide a field into subfield: Suppose you have a date field DATE1 of length 8 in the format mmddyyyy in externally described file. By using datastructure, you can divide the DATE1 field into days, months and years. Example D DATE1 D months D days D year DS 2 2 4 5.1.2. Group fields: Suppose you have a month, day, year fields in your externally described file. By using datastructure, you can combine all these fields into DATE1 in the format of year, month, day Example D Date1 D year D months D day DS 4 2 2 5.1.3. Define Externally described data structures: Assume FILEA contains fields FLD1 and FLD2. By using externally described datastructures, you can rename field FLD1 and you can initialize FLD2 with ‘Hello’ as follows: Example D ExtName E DS D Field1 E D FLD2 E EXTNAME(FILEA) EXTFLD(FLD1) INZ(‘Hello’) With EXTNAME keyword, specify the name of the externally described file. With EXTFLD, the name of FLD1 has been changed to Field1. 5.1.4. Define Data area data structures: A data area is an object that may exist permanently or temporarily in any library on the system. A data area data structure in an RPG IV program and the related data area must have the same name. Data areas may be implicitly or explicitly retrieved and written. When the data area is defined in an RPG IV program as a data area data structure, its data is implicitly retrieved for processing and written back(updated) at the end of the program. AS/400-RPGLE-SN-2.0 Page No. 25 ILE RPG/400 Example CRTDTAARA DTAARA(NAME) LEN(30) VALUE(‘Wipro Technologies’) To access this data area in your program, D Name UDS D Firstname 5 D Secondname 15 D Thirdname 30 5.1.5. Define Multiple occurance data structures: To define a multiple occurance data structure of 20 elements with : - 3 fields of character 20. - a 4th field of character 10 which overlaps the 2nd field starting at the second position. Example D twenty D MulDS D field1 D field2 D field21 D field3 C DS CONST(20) OCCURS(twenty) 1 20 21 40 22 31 41 60 5.2. Data structures can be program-described or externally-described. A program-described data structure is identified by a blank in position 22 of the definition specification. An externally-described data structure, identified by an E in position 22 of the definition specification, has subfield descriptions contained in an externally-described file, At compile time, the ILE RPG/400 compiler uses the external name to locate and extract the external description of the data structure subfields. You specify the name of the external description either in positions 7 through 21, or as a parameter for the keyword EXTNAME. An external subfield name can be renamed in the program using the keyword EXTFLD. The keyword PREFIX can be used to add a prefix to the external subfield names. Additional subfields can be added to an externally described data structure by specifying program-described subfields immediately after the list of external subfields. 5.3. SPECIAL DATA STRUCTURES: Special data structures include: 5.3.1. 5.3.2. 5.3.3. Data area data structure File inforamtion data structure (INFDS) Program-status data structure 5.3.1. Data area data structure: A data area data structure, identified by a U in position 23 of the definition specification, indicates to the RPG IV program that it should read in and lock the data area of the same name at program initialization and should write out and unlock the same data area at the end of the program. The data area and data area data structure must have the same name unless you rename the data area within the RPG IV program by using *DTAARA DEFINE operation code or the DTAARA keyword. If you specify blanks for the data area data structure ( positions 7 through 21 of the definition spec that contains a U in position 23), the RPG IV program uses the local data area. To AS/400-RPGLE-SN-2.0 Page No. 26 ILE RPG/400 provide a name for the local data area, use the *DTAARA DEFINE operation, with *LDA in factor 2 and the name in the result field or DTAARA(*LDA) on the definition specification. Examples for File information and program status data structure will be depicted in Exception/Error Handling chapter. 5.3.2. File Inforamtion data structure: You can specify a file inforamtion data structure( defined by the keyword INFDS on a file description specifications) for each file in the program. This provides you with status information on the file exception/error that occured. A file inforamation data structure contains predefined subfields that provide inforamtion on the file exception/error that occured. 5.3.3. Program-status data structure: A program-status data structure, identified by an S in position 23 of the definition specification, provides program exception/error inforamtion to the program. AS/400-RPGLE-SN-2.0 Page No. 27 ILE RPG/400 6. TABLE AND ARRAY PROCESSING Arrays and Tables are both collections of data fields(elements) of the same field length, data type, format. This chapter describes: 6.1. Differences between Arrays and Tables 6.2. Arrays 6.2.1. Prerun-time arrays 6.2.2. Compile-time arrays 6.2.3. Run-time arrays 6.3. Searching Arrays 6.3.1. Searching an Array without an Index 6.3.2. Searching an Array with an Index 6.4. Sorting an Array 6.5. How Tables differs from Array in coding 6.1. DIFFERENCES BETWEEN ARRAYS AND TABLES: Arrays and Tables differ in that: You can refer to a specific array element by its position You cannot refer to specific table elements by their position An array name by itself refers to all elements in the array. A table name always refers to the element found in the last “LOOKUP(Look up a Table or Array Element)” operation. During processing, elements in related arrays may be cross-referenced by indexing. 6.2. Arrays: An array may be defined as an arrangement of computer memory positions with each position having the same attributes. Loading an array refers to the time in the program cycle during which data is read, moved and stored in the array elements. There are three types of arrays. The Compile-time array is loaded when your program is created. The initial data becomes a permanent part of your program. The Prerun-time array is loaded from an array file when your program begins running, before any input, calculation, or output operations are processed. The run-time array is loaded by your program while it is runnig. 6.2.1. Compile-time array: A compile-time array is specified using the essential array specifications plus the keyword CTDATA. You can specify the number of array entries in an input record using the PERRCD keyword on the definition specification. If you do not use the PERRCD keyword, the number of entries defaults to 1. AS/400-RPGLE-SN-2.0 Page No. 28 ILE RPG/400 Example: Write a program which accepts month name and tells whether it is a valid month or not. *************** Beginning of data ************************************* 0001.00 Ddaynam s 3a dim(7) perrcd(2) CTDATA 0001.01 *daynam is a compile time array consisting of 7 elements. 0001.02 *daynam consists of two elements per record. 0002.00 Dname s 3a 0003.00 C 'Day name:?' dsply name 0003.01 *Searching whether the name is in array or not. 0004.00 C name lookup daynam 0005.00 C if *in20 0006.00 C 'valid' dsply 0007.00 C else 0008.00 C 'invalid' dsply 0009.00 C endif 0010.00 C seton l 0010.01 *Compile time array 0011.00 **CTDATA daynam 0012.00 montue 0012.00 montue 0013.00 wedthu 0014.00 frisat 0015.00 sun ****************** End of data **************************************** Compile-time arrays in alternating format: Code two arrays with 7 elements each. Name is a character array of length 3, and Number is a numeric array of length 1. To code a compile-time array in alternating format. Example: To code an alternating arrray, use ALT keyword. DNAME D DNUMBER S 15 S 1 0 DIM(7) PERRCD(3) CTDATA DIM(7) ALT(NAME) Declare the data as follows ** CTDATA Mon1 Tue2 Wed3 Thu4 Fri5 Sat6 sun7 6.2.2. Prerun-time array: For a prerun-time array, enter array input data into a file. The file must be a sequential program described file. By modifying this file, you can alter the array’s initial values on the next call to the program. The file is read in arrival sequence. On the definition specifications, in addition to the essential array specifications, you can specify the name of the file with the array input data, using the FROMFILE keyword. You can use the TOFILE keyword to specify the name of a file to which the array is written at the end of the program. You can use PERRCD keyword to specify the number of elements per input record. Specify a T in position 18 of the file description specifications for the file with the array input data. AS/400-RPGLE-SN-2.0 Page No. 29 ILE RPG/400 Example: Array ARH has 250 character elements(12 elements per record). Each element is five positions long. ARH is written back to the same file form which it is read when the program ends normally with LR on. DARH S 5A DIM(250) PERRCD(12) ASCEND D FROMFILE(DISKOUT) D TOFILE(DISKOUT) 6.2.3. Runtime arrays: If you make no further specifications beyond the essential array specifications, you have defined a run-time array. Noth that keywords ALT, CTDATA, FROMFILE, PERRCD and TOFILE connot be used for a run-time Example to declare a runtime array with 12 elements, each of length 3 is as follows: DARY1 S 3A DIM(12) Loading a Run-time array: You can assign initial values for a run-time array using the INZ keyword on the definition specification. You can assign values for a run-time array in calculation specifications. For example, you can use MOVE or MOVEL operation to load certain elements of an array. You can assign values for a run-time array through input specifications. If the array elements are consecutive on the input record, the array can be loaded with a single input specification. Suppose FILEA(program described file contains a record of length 9. If you want to load that record into an array of dimention 3, use the following code: *Using a run-time array with consecutive elements DARR1 S 12A DIM(3) *ARR1 is loaded with reocrd in FILEA. IFILEA AA 01 I 1 12 ARR1 If the array elements are scattered throughout the record, they can be defined and loaded one at a time, with one element described on a specification line. Following is an example shows loading an array ARR1, of six elements with 12 characters each, from a single record from file FILEA; a blank seperates each of the elements from the others. *Defining a runtime array with scattered elements D ARR1 S 12A DIM(6) I FILEA I I I I I I AA 01 1 14 40 66 12 ARR1(1) ARR1(2) 27 38 ARR1(3) 51 ARR1(4) 53 64 ARR1(5) 77 ARR1(6) 25 6.3. Searching Arrays: The LOOKUP operation can be used to search arrays. Searching an Array without an index: AS/400-RPGLE-SN-2.0 Page No. 30 ILE RPG/400 When searching an array without an index, use the resulting indicators to determine whether a particular element is present in the array. Searching an array without an index can be used for validity checking of input data to determine if a field is in a list of array elements. The search starts at the beginning of the array and ends at the end of the array or when the conditions of the lookup are satisfied. Whenever an array element is found that satisfies the type of search being made(equal, high, low), the resulting indicator is on. Example: suppose there is an array Months containing all the names of the months in a year. C ‘January’ LOOKUP Months 20(Equal indicator) The indicator 20 is set on because the search argument ‘january’ is in the list of elements of Months. Searching an Array with an index: To findout which element satisfies a LOOKUP search and start the search at a particular element in the array, search the array with an index. Example: Suppose you want to start the search from second element in an array and display the index where search has become successful * To start the search from 2nd element in the array ARR1 C Z-ADD 2 X 3 0 C ‘March’ LOOKUP Months(X) 20(Eq) *At the end of successful LOOKUP, 20 is set on. The index X contains the index of the element which is *equal to the ‘March’ 6.4. Sorting Arrays: You can sort arrays using the ‘SORTA’(sort an array) operation code. The array is sorted into sequence ( ascending or descending ), depending on the sequence specified for the array on the definition specification. C SORTA ARR1 6.5. How Tables differ from arrays in coding: Note: Using Tables in program is almost same as using arrays except in the following areas. Defining: A table name must be a unique symbolic name that begins with the letters TAB. Loading: Tables can be loaded only at compile time and prerun time. Using and Modifying table elements: Only one element of a table is active at one time. The table name is used to refer to the active element. An index cannot be specified for a table. Searching: AS/400-RPGLE-SN-2.0 Page No. 31 ILE RPG/400 LOOKUP with One Table: Whenever a table element is found that satisfies the type of search being made (equal, high, low), that table element is made the current element for the table. Resulting indicators reflect the result of the search. LOOKUP with two tables: When two tables are used in a search, only one is actually searched. When the search condition (high, low, equal) is satisfied, the corresponding elements are made available for use. Factor 1 must contain the search argument, and factor 2 must contain the name of the table to be searched. The result field must name the table from which data is also made available for use. A resulting indicator must also be used. Example: *The LOOKUP operation searches TABEMP for an entry that is equal to the contents of the field named EMPNUM. If an equal entry is found in TABEMP, indicator 09 is set on, and the TABEMP entry and its related entry in TABPAY are made the current elements. C EMPNUM AS/400-RPGLE-SN-2.0 LOOKUP TABEMP TABPAY 09 Page No. 32 ILE RPG/400 7. POINTERS Pointers are another important feature of ILE RPG/400 langurage. Although they may appear a little confusing for a beginner, they are a powerful tool and handy to use once they are mastered. There are a number of reasons for using pointers. 1. 2. 3. 4. 5. A pointer enables us to access a variable that is defined outside the function. Pointers are more efficient in handling the data tables. Pointers reduce the length and complexity of a program. They increase the execution speed. The use of a pointer array results in saving of data storage space in memory. In this chapter, We will examine the pointers in detail and learn how to use them in development. This chapter explains the following topics: 7.1. Understanding pointers 7.2. Declaring a pointer data type 7.3. Dynamic memory allocation 7.4. Pointers to functions 7.1. Understanding Pointers: As you know, computers use their memory for storing the instructions of a program, as well as the values of the variables that are associated with it. The computer’s memory is a sequential collection of ‘storage cells’. Each cell commonly known as a byte, has a number called address associated with it. Typically, the addresses are numbered consecutively, starting from zero. The last address depends on the memeory size. A computer system having 64K memory will have its last address as 65,535. Whenever, we declare a variable, the system allocates, somewhere in memory, an appropriate location to hold the value of the variable. Since, every byte has a unique address number, this location will have its own address number. Consider the following statement: D Name S 5A INZ(‘WTH’) This statement instructs the system to find a location for the variable Name and puts the value ‘WTH’ in that location. Let us assume that the system has choosen the address location 5000 for Name. We may represent this as follows Variable Name Value WTH Address 5000 We may have access to the value ‘WTH’ by using either the name ‘Name’ or the address 5000. Since memory addresses are simply numbers, they can be assigned to some variables which can be stored in memory, like any other variable. Such variables that hold memory addresses are called pointers. A pointer is, therefore, nothing but a variable that contains an address which is a location of another variable in memory. Remember, since a pointer is a variable, its value is also stored in the memory in another location. Suppose, we asssign the address of ‘Name’ to a variable ‘P’. The link between the variables P and Name can be visualized as follows: Variable AS/400-RPGLE-SN-2.0 Value Address Page No. 33 ILE RPG/400 Name WTH 5000 P 5000 5048 Since the value of variable P is the address of the variable ‘Name’, we may access the value of Name by using the value of P and therefore, we say that the variable P ‘points’ to the variable ‘Name’. Thus, P gets the name Pointer. 7.2. Declaring a Pointer data type: Consider the following: *************** Beginning of data ************************************* 0001.00 Dptr1 s * 0002.00 Dfld1 s 14a based(ptr1) 0003.00 C alloc 14 ptr1 0004.00 C move *all'a' fld1 0006.00 C seton lr ****************** End of data **************************************** When the BASED keyword is specified for a data structure or standalone field, a basing pointer is created using the name specified as the keyword parameter. The basing pointer holds the address(storage location) of the based datastructure or standalone field being defined. Note: Before the based datastructure or standalone field can be used, the basing pointer must be assigned a valid address. Following gives a detailed explanation of the above example: ptr1 is a pointer field fld1 is a field of length 14. Ptr1 is going to hold the address of fld1. 14 bytes of storage was allocated and ptr1 points to that starting address. We must allocate memory to ptr1 otherwise fld1 is cannot be used. a is filled in all 14 positions of fld1. After executing these statements, the representation of variables is as follows: Variable fld1 ptr1 Value aaaaaaaaaaaaaa address of fld1.(ie., address of value aaaaaaaaaaaaaa) Declaring a pointer over an array: D MBRPTR S D MBRARR S * 10 BASED(MBRPTR) DIM(32767) In this example, we code the DIM for the number of maximum elements allowed, nothing that no storage will actually be declared for this definition( because it is BASED) In the above, only declaration of pointers was explained. The other concepts will be covered later. 7.3. Dynamic Memory Allocation: Introduction: Most often we face situations in programming where the data is dynamic in nature. That is, the number of data items keep changing during execution of the program. For example, consider a AS/400-RPGLE-SN-2.0 Page No. 34 ILE RPG/400 program for processing the list of customers of an organization. The list grows when the names are added and shrinks when names are deleted. Dynamic data structures provide flexibility in adding, deleting or rearranging data items at run time. Dynamic memory management techniques permit us to allocate additional memory space or to release unwanted space at run time, thus, optimizing the use of storage space. This topic discusses the concept of linked lists, one of the basic types of dynamic data structures. Dynamic Memory Allocation: ILE RPG IV requires the number of elements in an array to be specified at compile time. But we may not be able to do so always. Our initial judgement of size, if it is wrong, may cause failure of the program or wastage of memory space. You can use the following RPG operations on the dynamic storage allocation The ALLOC oerpation allocates storage wihin the default heap. The DEALLOC operation frees one previous allocation of heap storage. The REALLOC operation changes the size of previously allocated storage from any heap. Example: Assume that Data entry operation of an organization doesn’t know the total number of employees. He has to enter all the names one by one and atlast he has to print the list of all employees. AS/400-RPGLE-SN-2.0 Page No. 35 ILE RPG/400 The following example takes the names of the employees until end is given. Then displays all the employee names. 0001.00 DAddname pr 0002.00 D namein 20a 0003.00 Ddisplay pr 0004.00 Dfree pr 0005.00 Demp ds based(emp@) 0006.00 D name@ * 0007.00 D next@ * 0008.00 Dnam s 20a based(name@) 0009.00 Dempsize c %size(emp) 0010.00 Dfirst ds 0011.00 D * INZ(*Null) 0012.00 D * inz(*null) 0013.00 Demp@ s * inz(%addr(first)) 0014.00 C 'Emp Name:?' dsply namein 20 0015.00 C dow namein <> 'end' 0016.00 C callp addname(namein) 0017.00 C 'Emp Name:?' dsply namein 20 0018.00 C enddo 0019.00 C callp display 0020.00 C callp free 0021.00 c seton lr 0022.00 Paddname b 0023.00 daddname pi 0024.00 D namein 20a 0025.00 c alloc empsize next@ 0026.00 C eval emp@ = next@ 0027.00 C eval next@ = *null 0028.00 C alloc 20 name@ 0029.00 C eval nam = namein 0030.00 Paddname e 0031.00 Pdisplay b 0032.00 dsemp@ s * 0033.00 C eval semp@ = emp@ 0034.00 C eval emp@ = %addr(first) 0035.00 C dow next@ <> *null 0036.00 C eval emp@ = next@ 0037.00 C nam dsply 0038.00 C enddo 0039.00 C eval emp@ = semp@ 0040.00 Pdisplay e 0041.00 Pfree b 0042.00 Dprv@ s * 0043.00 C eval emp@ = %addr(first) 0043.00 C eval emp@ = %addr(first) 0044.00 C eval emp@ = next@ 0045.00 C dow emp@ <> *null 0046.00 C dealloc name@ 0047.00 C eval prv@ = emp@ 0048.00 C eval emp@ = next@ 0049.00 C dealloc prv@ 0050.00 C enddo 0051.00 C eval emp@ = %addr(first) 0052.00 Pfree e ****************** End of data **************************************** AS/400-RPGLE-SN-2.0 Page No. 36 ILE RPG/400 7.4. Pointers to Procedures: A procedure, like a variable, has an address location in the memory. It is therefore, possible to declare a pointer to a function, which can then be used as an argument in another function. The following example explains how to use pointers to procedures. First create a module with the following source *************** Beginning of data ************************************* 0001.0 Hnomain *Enjoy is a procedure, it can be used in other modules. It just displays HELLO. 0002.00 DENJOY pr 0003.00 PENJOY B export 0004.00 DENJOY pi 0005.00 C 'HELLO' DSPLY 0006.00 PENJOY E ****************** End of data **************************************** Create another module with the following source First it declares a procedure pointer ‘penjoy’ which is initialized with address of ENJOY procedure. Use CALLB to call procedure with procedure pointer. *************** Beginning of data ************************************* 0001.00 DENJOY pr 0002.00 Dpenjoy s * procptr inz(%paddr('ENJOY')) 0003.00 c callb penjoy 0004.00 C seton lr ****************** End of data **************************************** After creating abvoe two modules create a program by including these two modules. Then call the program. The message ‘HELLO’ is displayed. AS/400-RPGLE-SN-2.0 Page No. 37 ILE RPG/400 8. EXCEPTION AND ERROR HANDLING Exception errors that cause program execution to cancel are not uncommon in the programming environment. Exception handling is the process of examining an exception message which has been issued as a result of a run-time error. When a run-time error occurs, an exception message is generated. An exception message has one of the following types depending on the error which occured: ESCAPE Indicates that a severe error has been detected. STATUS Describes the status of work being done by a program NOTIFY Describes a condition requiring corrective action or reply from the calling program. Function check indicates that one of the three previous exceptions occured and was not handled. Exception handlers are used to handle exception messages. Each call stack entry is associated with a list of exception handlers defined for that entry. In general, when an exception occurs, the handlers associated with the call stack entry are given a chance to handle the exception. If the exception is not handled by any of the handlers on the list the following default actions are taken: 1. 2. 3. If the exception is a function check, the call stack entry is removed from the stack. The exception is moved(percolated) to the previous call stack entry. The exception handling process is restarted for this call stack entry. Percolation is the action of allowing the previous call stack entry to handle an exception. This chapter explains the following topics: 8.1. Difference between OPM and ILE RPG/400 Exception handling 8.2. Usingg RPG-Specific Handlers 8.2.1.Specifying error indicators 8.2.2.Using a File Error ( INFSR ) subroutine 8.2.3 Using a Program Error Subroutine ILE RPG/400 supports not only RPG-specific handlers. It also supports ILE condtion handlers, user-written exception handlers that you register at run time using the ILE condition handler bindable API CEEHDLR. ILE RPG/400 also supports ILE cancel handler which can be used when a procedure ends abnormally. I haven’t covered ILE conditon handlers and ILE cancel handlers. 8.1. Difference between OPM and ILE RPG/400 Exception Handling: The key difference lies in the area of unhandled exceptions. In OPM, if an exception occurs and there is no RPG-specific handler enabled, then an inquiry message is issued. In ILE, this will only occur if the exception is a function check. If it is not, then the exception will be passed to the caller of the procedure or program, and any eligible higher call stack entries are given a chance to handle the exception. For example, consider the following example: PGM A calls PGM B, which in turn calls PGM C. PGM B has an error indicator coded for the call. PGM C has no error indicator or *PSSR error subroutine coded. PGM C gets an exception In OPM, an inquiry message would be issued for PGM C. In ILE, the exception is percolated to PGM B, since it is unhandled by PGM C. The error indicator in PGM B is turned on allowing PGM B to handle the error, and in the process PGM C ends abnormally. AS/400-RPGLE-SN-2.0 Page No. 38 ILE RPG/400 8.2. Using RPG-Specific Handlers: There are three ways for you to indicate that RPG should handle an exception. You can: Specify an error indicator in positions 73 - 74 of the calculation specifictions of the apporpriate operation code 2. Code a file error subroutine, which is defined by the INFSR keyword on a file description specification, for file exceptions. 3. Code a program error subroutine, which is named *PSSR, for program exceptions. Note that a *PSSR is local to the procedure in which it is coded. This means that a *PSSR in a main procedure will handle only those program errors associated with the main procedure. Similarly, a *PSSR in a subprocedure will only handle the errors in that subprocedure. 1. You can obtain more inforamtion about the error which occured by coding the appropriate data structures and querying the relevant data structure fields. 8.2.1. Specifying error indicators: To enable the RPG error indicator handler, you specify an error indicator in positions 73 and 74. If an exception occurs on the oepration, the indicator is set on, the appropriate data structure (PSDS or INFDS) is updated, and control returns to the next sequential instruction. You can then test the indicator to determine what action to take. When you specify an error indicator on an operation code, you can explicitly call a file error subroutine (INFSR) or a program error subroutine ( *PSSR) with the EXSR operation. 8.2.2. Using a File Error ( INFSR ) subroutine: To handle a file error or exception in a main procedure you can write a file error (INFSR) subroutine. When a file exception occurs: 1. 2. The INFDS is updated. A file error subroutine (INFSR) receives control if the exception occurs. To add a file error subroutine to your program, you do the following steps: Enter the name of the subroutine after the keyword INFSR on a file description specification. Optionally identify the file information data structure on a file description specification using the keyword INFDS. 3. Enter a BEGSR operation where the factor 1 entry contains the same subroutine name that is specified for the keyword INFSR. 4. Identify a return point and code it on the ENDSR operation in the subroutine. 5. Code the rest of the file error subroutine. 1. 2. Example: The following program accepts employee number from user and updates the company name of that employee to BMD. If record lock is there on that particular record, it displays the message ‘record is locked’ The DDS for the file EMPDATA is as follows: *************** Beginning of data ************************************* 0001.00 A R EMPR 0002.00 A NUM 5 0 0003.00 A COMPNAME 15A 0004.00 A K NUM ****************** End of data **************************************** AS/400-RPGLE-SN-2.0 Page No. 39 ILE RPG/400 The RPG-IV code is as follows: *************** Beginning of data ************************************* 0001.00 Fempdata uf e k disk 0002.00 F infsr(errr) 0003.00 F infds(errs) 0004.00 Derrs ds 0005.00 D rstatus *status 0006.00 C 'Name:?' dsply no 50 0007.00 C no chain empdata 90 0008.00 C if not *in90 0009.00 C move(p) 'BMD' compname 0010.00 C update empr 0011.00 C endif 0012.00 C seton lr 0013.00 C errr begsr 0013.01 *When record lock is there, rstatus becomes 1218 0014.00 C if (rstatus = 1218) 0015.00 C 'record lock' dsply 0016.00 C endif 0017.00 C endsr ****************** End of data **************************************** 8.2.3. Using a Program Error Subroutine: To handle a program error or exception you can write a program error subroutine ( *PSSR ). When a program error occurs: 1. 2. The program status data structure is updated. If an indicator is not specified in positions 73 and 74 for the operation code, the error is handled and control is transferred to the *PSSR. You can explicitly transfer control to a program error subroutine after a file error by specifying *PSSR after the keyword INFSR on the file description specifications. You can code a *PSSR for any (or all) procedures in the module. Each *PSSR is local to the procedure in which it is coded. To add a *PSSR error subroutine to your program, you do the following steps: Optionnally identify the program status data structure (PSDS) by specifying an S in positions 23 of the definition specification. 2. Enter a BEGSR operation with a Factor 1 entry of *PSSR. 3. Identify a return point, if any, and code it on the ENDSR operation in the subroutine. 4. Code the rest of the program error subroutine. 1. Example: Define relevant parts of program status data structure D PSDS D Loc D Err D Parms AS/400-RPGLE-SN-2.0 SDS *ROUTINE *STATUS *PARMS Page No. 40 ILE RPG/400 *In the *PSSR subroutine, code for division by zero, trying to get squareroot of negative number etc., C *PSSR BEGSR C IF Err = 102 C* Write your own code here C ENDIF C ENDSR AS/400-RPGLE-SN-2.0 (For division by zero error) Page No. 41 ILE RPG/400 9. BUILT-IN FUNCTIONS Built-in functions are similar to operation codes in that they perform operations on data you specify. All built-in functions have the percent symbol (%) as their first character. The following explains the built-in functions, their arguments, and the value they return with examples. 1. %ADDR ( Get Address of Variable ) %ADDR returns a value of type basing pointer. The value is the address of the specified variable. Example: D Fld1 C CONST(7) D Ptr S * INZ(%ADDR(Fld1)) 2. %ELEM ( Get Number of Elements ) %ELEM returns the number of elements in the specified array, table, or multiple occurance data structure. Example: D Arr1 S 20 DIM(10) C 3. EVAL num = %ELEM (Arr1) %PADDR ( Get Procedure Address ) %PADDR returns a value of type procedure pointer. The value is the address of the entry point specified as the argument. Example: D Proc S * PROCPTR INZ(%PADDR(‘FIRSTPROG’)) 4. %SIZE: %SIZE returns the number of bytes occupied by the constant or field. The argument may be a literal, a named constant, a data structure, a data structure subfield, a field, an array or a table name. Example: D table1 S 5 DIM(20) C 5. EVAL num = %SIZE(table1) %SUBST: %SUBST returns a portion of argument string. It may also be used as the result of an assignment with the EVAL operation code. Example: The value of %subst(‘hello world’:4:3) is lo 6. %TRIM: %TRIM returns the given string less any leading and trailing blanks Example: The value of %TRIM(‘ hello ‘) is ‘hello’ 7. %TRIML: %TRINL returns the given string less any leading blanks. 8. TRIMR: %TRIMR returns the given string less any trailing blanks. AS/400-RPGLE-SN-2.0 Page No. 42