You are on page 1of 230

RPG-ILE LABS

NAV IGA TI ON CHA RT

DAY 1 DAY 2 DAY3 DAY 4

COMPARISON COMPILER Data Type TESTING


CHART DIRECTIVE Conversion

CHEAT SHEETS ADVANCED PROCEDURES LOGIC CYCLE


DATABASE and MODULES.
PROCESSING Bind by COPY
and REFERENCE
FEATURES FLAT PHYSICAL
FILE

EMBEDDED SQL SERVICE PROJECT


OPERATION PROGRAM
EXTENDERS API

BASICS RLU BINDER SIX DAYS


LANGUAGE BREAKUP
I Specs

ARRAYS

BUILT IN DATA Q
FUNCTIONS PROGRAMMING MISC

DATA AREA ERROR HANDLING* POINTERS HUB ILE coding


style
DATE TIME MESSAGING FREE
PROGRAMMING
NEW KEYWORDS MONITOR Memorc
DATA
STRUCTURES

SUBFILES KA and KB ACTIVATION


indicators GROUP
ODP
STRING VALIDATION
OPERATION

1
RPG-ILE LABS

DISPLAY FILES SMALL UTILITY PROJECT (imp !!!)


Indicator data
structure PROJECT

DATABASE
PROCESSING

2
RPG-ILE LABS

SIX
DAYS
BREAKUP

Day Remarks
Coverage
1 COMPARISON CHART FEATURES CHEAT SHEETS OPERATION EXTENDERS
BASICS ARRAYS BUILT IN FUNCTIONS DATE TIME PROGRAMMING DATA
STRUCTURES
2 DATA AREA STRING OPERATION VALIDATION SUBFILES API RLU
3 DISPLAY FILES COMPILER DIRECTIVE Data Type Conversion
4 ADVANCED DATABASE PROCESSINGERROR HANDLING ODP PROCEDURES and
MODULES. Bind by COPY and REFERENCE SERVICE PROGRAM BINDER
LANGUAGE ACTIVATION GROUP
5 DATA Q PROGRAMMING MESSAGING EMBEDDED SQL LOGIC CYCLE MONITOR
TESTING POINTERS FREE SMALL UTILITY PROJECT (imp !!!)
6
Assignments

3
RPG-ILE LABS

SMAL L UTILI T Y PR O JEC TS ( Use ILE built in functions where possible. )

1. Utility to accept object name from user and display locations where the sources of the object are present.
2. Compare utility : Compare contents of 2 members of a source physical file and produce a report.
3. Utility to locate all libraries where specified object is present and write the libraries to a physical file.
4. Utility to locate source member and source physical file of the specified object and store it to a database
file. Following report should be created :-

Objec Object Src. P F. Sr c. Sou rce


t Library Member Library
Name Names

PF001 L1 MySRC PF001 Lib002


L2 SamSRC PF001 Lib003
L3 SamSRC PFCUST Lib001
L4 QDBHSRC CUSTDATA L4
PF002 L11 MySRC MPF001 GHOHUBSPH
L22 EMOSRCDBF PF002 GHOHUBCPH

5. Utility to display all members of a source PF. User selects a few members. Combine all members and store
them to a new member (name specified by user). The data for each member should be easily identifiable.

6. Write a utility to accept member name and type from user and set of libraries to search. After user
finishes entering the libraries (or asks you to refer to the library list), search each for presence of that
member (search all source physical files in the library) for presence of that member.

7. RPGLE editor : Create a simple multi-Document Editor, which behaves like Notepad. (Notepad /400 ! )
8. A utility to display all physical and logical files containing XXXX entered by user ( eg. : User enters
“FSTS” as a search string. The utility scans the library list / list of libraries specified by user and displays
names and libraies of all Physical files and logical files containing the specified field name.)

9. Utility to display all source physical files present in all libraries in the library list and write the list to a
database.

File compi la tion u til ity

1. A Physical file P1 may have several logical files (say L1,L2,L3,L4 … ) based on it. Programmer makes a
change to DDS of the Physical file and updates the PF object using CHGPF. This does not automatically
update the LFs sicne they all use old definition. To update all Logical files, you need to compile all of
them. This can get quite tedious. Build a utility to automatically determine and compile all the logical
files.

2. Write a Utility to read source code of a program (member name will be specified by user) and write it to a
spool file after indenting it. Indentation will be provided to IF statements and Do loops.

** *

4
RPG-ILE LABS
1.
P ROJ ECT S

1. A new module is to be developed for a bank. The module is for Calculation of interest on Saving A/c. It
should allow inputing new customer, and saving any transactions done by the customer. For formula of
calculating interest , see EPM.

2.

5
RPG-ILE LABS

RPG - IL E LA BS
LAB : Source Physical file : QRPGLESRC

LAB : Study of new Specs : HFDICOP. Structure and purpose of each. New Spec : CX.

F : SPEC :

6
RPG-ILE LABS

LAB : Data Types in RPGLE.Member type and compilation commands.

A : Character
B : fixed Binary
D : date Field
F : Floating point
G : Graphics character set
I : Signed Integer
P : Packed Decimal
S : Zoned Field
T : Time field
U : Unsigned Integer Field
Z : Timestamp Field
* : Pointer Field

LAB : Introduction of RPG programing. Declaring Variables in RPG.

DA01 S 2P 0 Inz(-1)
C*

7
RPG-ILE LABS

C A01 DSPLY
C*
C EVAL *INLR = *ON

DCON1 C CONST('ABCDEFGHIJKLMNOPQRSTUVWXYZ+
D cdefghijklmnopqrstuvwxyz')
C CON1 DSPLY
C EVAL *INLR = *ON
LAB : RPG Constructs IF, DOW, DO, DOU,LEAVE ,ITER.

* Declare a variable.Display a string,float and integer


* =====================================================
Djsr S 20A
Djsr1 S 20A
C EVAL jsr1= 'string1'
C EVAL jsr = 'string2'
C if jsr1 <> jsr
C EVAL jsr1='xx'
C endif
C jsr1 DSPLY
C EVAL *INLR = *ON

LAB : DO WHILE

* (DEMO OF DO WHILE LOOP)


DN S 5i 0
C DOW N <=4
C EVAL N=N+1
C N IFEQ 2
C ITER
C ENDIF
C N DSPLY
C ENDDO
C EVAL *INLR = *ON
Output : 1 3 4

Output : 1 2 3 4 5

LAB : ROUNDING RESULTS OF CALCULATION

LOGIC :

1.124
+ 0.001
-----
1.13 (ROUNDED)
1.12 (NOT ROUNDED)

DISPLAY FILE DDS :


A DSPSIZ(24 80 *DS3)
A R R1
A 5 9'WITHOUT ROUNDING : '

8
RPG-ILE LABS

A 7 9'WITH ROUNDING : '


A DTOTAMT1 5Y 2B 5 30EDTCDE(Q)
A DTOTAMT2 5Y 2B 7 30EDTCDE(Q)

RPGLE PROGRAM :

FDSRND CF E WORKSTN
DCRS S 5S 3 INZ(1.121)
DRATE S 5S 3 INZ(0.001)
DTOTAMT1 S 5S 2 INZ(0)
DTOTAMT2 S 5S 2 INZ(0)
C DO 5
C EVAL TOTAMT1 = RATE + CRS
C* now try with (H) for Rounding.
C EVAL(H) TOTAMT2 = RATE + CRS
C EVAL DTOTAMT1 = TOTAMT1
C EVAL DTOTAMT2 = TOTAMT2
C EXFMT R1
C EVAL RATE = RATE + 0.001
C ENDDO
C SETON LR

LAB : Interactive Source Debugger

Step 1 : Compile the program with Debugging Views set to *SOURCE. This allows the
Debugger to access the source code of the program and display it.

Step 2 : Use STRDBG and press F4. Specify “Display Module Source “ parameter as
*YES. Press Enter.

Step 3 : The Source code will be displayed. Take the cursor to the line that needs a
break point and press F6.

In the Figure above, the break point is set at Line 2.


Perss F10 to to exit out and call the LE02 program. It is displayed in the debugger.
The control will be at first executable line. Press F10 to step through the code.

9
RPG-ILE LABS

To Display the current value of a variable : Bring the cursor under the variable and
press F11.
Press F3 to exit Debugger. Issue the ENDSBG command to end the Debug mode.

LAB : LEAVESR : to leave a Sub routine !

Linkage : RPLEAVE

CODE :

da s 4s 0 inz(4)
d
c 'BEfore SR' dsply
c ExSR SR001
c 'After SR' Dsply
c Eval *inlr = *on
c Return
c*
c SR001 BegSR
c 'SR starting' Dsply
c if a = 4
c LeaveSR
c EndIf
C* ----------------------------------------
C* The following line never gets executed !
C* ----------------------------------------
c 'Ending SR' Dsply
c EndSR

PF contents :

---

OUTPUT :

DSPLY BEfore SR
DSPLY SR starting
DSPLY After SR

REMARKS :

LeaveSR is to leave the currently executing SR.

LAB : For loop

dn1 s 4s 0 inz(0)
d
d
d
d
c For n1= 10 DOWNTO 1 by 2
c n1 dsply
c EndFOr
c Eval *inlr = *on
c Return

10
RPG-ILE LABS

If n1 increments :

c For n1= 1 TO 10 by 2

If n1 decrements :

c For n1= 10 DOWNTO 1 by 2

in both cases the step size is 2.

11
RPG-ILE LABS

Lab : H-SPECS

H DATFMT(*YMD)
DJSRDT1 S D INZ(D'04/12/10')
C JSRDT1 DSPLY
C SETON LR

H DATFMT(*YMD) CURSYM('£')
H* ALT 156 FOR POUND SIGN
H*
DJSRDT1 S D INZ(D'04/12/10')
DCIH S 7P 2 INZ(120.25)
C JSRDT1 DSPLY
C CIH DSPLY
C SETON LR

VALID DATE FORMATS :


*iso,mdy,*ymd,*jul,*usa,*jis,*eur

VALID TIME FORMATS:


*HMS *USA *EUR *JIS

SPECIFYING THE SEPERATOR FOR THE DATE FORMAT :


(SEE THE ONLINE HELP - EXCELLENT !)
H DATFMT(*DMY-)
H* date format is DMY and seperator char is - (dash)
DDT1 S D INZ(D'12-12-04')
c DT1 DSPLY
c SETON LR

LAB : USING OVERLAY FOR DATES

DDT1 DS
DDAT1 D DATFMT(*ISO-) INZ(D'1994-06-16')
DDATY 4 OVERLAY(DAT1:1)
DDATM 2 OVERLAY(DAT1:6)
DDATD 2 OVERLAY(DAT1:9)
C DT1 DSPLY
C DAT1 DSPLY
C DATY DSPLY
C DATM DSPLY
C DATD DSPLY
C SETON LR

LAB : Working with dates

HDATFMT(*DMY)
ddt1 s 8D inz(D'01/04/04')
c adddur 3:*days dt1
c adddur 3:*months dt1
c adddur 3:*Years dt1
c dt1 dsply
c* output is 04/07/07
c eval *inlr=*on

HDATFMT(*DMY)

12
RPG-ILE LABS

ddt1 s 8D inz(D'01/04/04')
ddt2 s 8D inz(D'01/03/03')
c dt1 adddur 3:*days dt2
c dt2 dsply
c*
c eval *inlr=*on

EXAMPLE 3 : SUBtract duration

HDATFMT(*DMY)
ddt1 s 8D inz(D'01/04/04')
ddt2 s 8D inz(D'01/03/03')
c dt1 subdur 3:*days dt2
c dt2 dsply
c* Output : 29/03/04
c eval *inlr=*on

HDATFMT(*DMY)
ddt1 s 8D inz(D'01/01/04')
ddt2 s 8D
dn s 2s 0 inz(31)
c dt1 adddur n:*days dt2
c dt2 dsply
c* Output : 01/02/04
c dt2 adddur n:*days dt2
c dt2 dsply
c* Output : 03/03/04
c eval *inlr=*on

HDATFMT(*DMY)
dds1 ds
dd 2s 0
dsep1 1a
dm 2s 0
dsep2 1a
dy 2s 0
ddt1 s 8D inz(D'15/02/04')
c movel dt1 ds1
c d dsply
c m dsply
c y dsply
c eval *inlr=*on

LAB : SUBDUR

H TIMFMT(*HMS:)
DDS1 DS
DSTARTTM T INZ(T'07:00:00')
DENDTM T INZ(T'10:21:00')
DH1 2S 0 OVERLAY(STARTTM:1)
DH2 2S 0 OVERLAY(ENDTM:1)
DM1 2S 0 OVERLAY(STARTTM:4)
DM2 2S 0 OVERLAY(ENDTM:4)
DTOTTIME S T INZ(T'00:00:00')
C STARTTM DSPLY
C ENDTM DSPLY
C H1 DSPLY
C H2 DSPLY

13
RPG-ILE LABS

C M1 DSPLY
C M2 DSPLY
C ENDTM SUBDUR H1:*H TOTTIME
C SUBDUR M1:*MN TOTTIME
C TOTTIME DSPLY
C SETON LR

OUTPUT : 03:21:00

LAB : SUBDUR

H TIMFMT(*HMS:)
DSTARTTM S T INZ(T'07:00:00')
DENDTM S T INZ(T'10:50:00')
DH1 S 3S 0
DM1 S 3S 0
C STARTTM DSPLY
C ENDTM DSPLY
C ENDTM SUBDUR STARTTM H1:*H
C ENDTM SUBDUR STARTTM M1:*MN
C H1 DSPLY
C M1 DSPLY
C SETON LR

OUTPUT :

DSPLY 07:00:00
DSPLY 10:50:00
DSPLY 3
DSPLY 230

LAB : SUBDUR

H DATFMT(*DMY/)
DSTARTDT S D INZ(D'10/12/04')
DENDDT S D INZ(D'15/12/04')
DDAYS S 3S 0
C ENDDT SUBDUR STARTDT DAYS:*D
C DAYS DSPLY
C SETON LR

OUTPUT :
5
LAB : ADDDUR

H DATFMT(*DMY/)
DSTARTDT S D INZ(D'10/12/04')
DENDDT S D
DDAYS S 3S 0 INZ(25)
C STARTDT ADDDUR DAYS:*D ENDDT
C ENDDT DSPLY
C SETON LR

OUTPUT :

04/01/05

LAB : ACCESSING SYSTEM DATE

H DATFMT(*DMY/)

14
RPG-ILE LABS

DENDDT S D DATFMT(*DMY)
C MOVE *DATE ENDDT
C ENDDT DSPLY
C SETON LR

OUTPUT : CURRENT SYSTEM DATE

LAB : Extracting date,month year fromdate

H DATFMT(*ISO)
DDT1 S D INZ(D'2004-12-10')
DTR S 4S 0 INZ(0)
C EXTRCT DT1:*Y TR
C TR DSPLY
C EVAL *INLR = *ON

LAB : TEST opcode to test validity of Date, time and Timestamp

H DATFMT(*ISO)
DDT1 S D INZ(D'2004-12-10')
DDT2 S 6S 0 INZ(041312)
DTR S 4S 0 INZ(0)
C TEST DT1 55
C* ____________________________
C* If date is not a valid date
C* with *ISO format,
C* IND 55 is TURNED ON.
C* ____________________________
C IF *IN55 = *OFF
C 'dt1 valid' DSPLY
C ENDIF
C* OUTPUT : DT1 VALID
C* Repeat this test for
C* DT2
C* ---------------------
C *YMD TEST(D) DT2 55
C* -----------------------
C* This date is not valid.
C* -----------------------
C IF *IN55 = *OFF
C 'DT2 valid' DSPLY
C ENDIF
C EVAL *INLR = *ON

Notes :

1. No need to specify *YMD or any other format in Factor 1, if the variable to


be tested is defined as Date/Time. Also OPERATION EXTENDER is not required if
the variable to be tested is of TYPE DATE TIME or TIMESTAMP.
2. IF a character or numeric variable is to be tested, specify the format in
Factor 1.
3. While testing DT1, the format for date is taken as *ISO.
4. While testing DT2, Format is taken from factor 1 and tested against the
contents of DT2. The month specified here is 13, which is not valid for a
month value. So indicator 55 is turned ON.

TESTING VALIDITY OF TIME

15
RPG-ILE LABS

H TIMFMT(*ISO)
DTM1 S T INZ(T'10.12.14')
DTM2 S 6S 0 INZ(101214)
C TEST TM1 55
C IF *IN55 = *OFF
C 'TM1 valid' DSPLY
C ENDIF
C* OUTPUT : TM1 VALID
C* Repeat this test for
C* TM2
C* ---------------------
C *HMS TEST(T) TM2 55
C* -----------------------
C* This TIME is not valid.
C* -----------------------
C IF *IN55 = *OFF
C 'TM2 valid' DSPLY
C ENDIF
c TM1 dsply
c TM2 dsply
C EVAL *INLR = *ON

TESTING VALIDITY OF TIMESTAMP

H TIMFMT(*ISO)
DTS1 S Z INZ(Z'2004-12-10-10.12.20.000000')
C TEST TS1 55
C IF *IN55 = *OFF
C 'TS1 valid' DSPLY
C ENDIF
C* OUTPUT : TS1 VALID
c TS1 dsply
C EVAL *INLR = *ON

LAB: Program to calculate days between 2 dates.

Program accepts date values into fields with edit code of Y. If a wrong date is unput
by the user, control directly enters PSSR.
Better approach of accepting dates is previous lab.

RPGLe program RPDATE1 :

H DATFMT(*DMY)
H* PROGRAM TO CALCULATE PENALTY. ISSUES DATE AND RECPT DATE ARE
H* ARE ACCEPTED. IF THE RECPT DATE IS 7 DAYS OR LESS, NO PENALTY.
H* FOR EVERY ADDITIONAL DAY, PENALTY IS Rs 5/- PER DAY.
H* ----------------------------------------------------------------
H*
FDSPENAL CF E WORKSTN
F*
DNODATE S 6S 0 INZ(0)
DNOTIME S 6S 0 INZ(0)
DDELTA S 4S 0 INZ(0)
DISDAT S D INZ(D'01/01/01')
DRCDAT S D INZ(D'01/01/01')
C DOW *IN03 = *OFF
C IF *IN03 = *ON
C EVAL *INLR = *ON

16
RPG-ILE LABS

C RETURN
C ENDIF
C*
C MOVE NODATE DISDAT
C MOVE NODATE DRCDAT
C EXFMT RDATE
C SETOFF 7778
C MOVE DISDAT ISDAT
C MOVE DRCDAT RCDAT
C RCDAT SUBDUR ISDAT DELTA:*D
C EVAL DELTA = DELTA - 7
C IF DELTA<0
C EVAL DPENAL = 0
C ITER
C ENDIF
C*
C DELTA MULT 5 DPENAL
C GONXT TAG
C ENDDO
C EVAL *INLR = *ON
C RETURN
C* ---------------------------------------------------
C *PSSR BEGSR
C SETON 7778
C GOTO GONXT
C ENDSR

Display file listing : DSPENAL

A DSPSIZ(24 80 *DS3)
A CA03(03)
A R RDATE
A 6 4'ISSUE DATE :'
A 8 4'RECPT DATE : '
A DISDAT 6Y 0B 6 19EDTWRD(' / / ')
A EDTMSK(' & & ')
A COLOR(WHT)
A 77 ERRMSG('INVALID DATA')
A DRCDAT 6Y 0B 8 19EDTWRD(' / / ')
A EDTMSK(' & & ')
A COLOR(WHT)
A 78 ERRMSG('INVALID DATA')
A 12 4'PENALTY AMOUNT : '
A DPENAL 4Y 0O 12 23EDTCDE(3)
A COLOR(RED)
A 12 29'Rs'

LAB : Loading date values to Physical file :

Physical File: PFDATE


RPG : RPDATE
Display : DSDATE

RPDATE Listing :

H DATFMT(*DMY)

17
RPG-ILE LABS

H* PROGRAM LOADS DATA INTO THE PFDATE PF. IT ACCEPTS 2 DATE VALUES
H* AND 2 TIME VALUES. THE VALIDATION OF THE VALUES IS DEFAULT BY
H* VIRTUE OF THEIR TYPE. NO VALIDATION SPECIFIED IN THE DISPLAY
H* FILE. IF WRONG DATA ENTERED, THE CONTROL GOES INTO PSSR.
H* CONTROL GOES INTO PSSR DURING A MOVE OPERATION, WHEN DDATE
H* IS BEING MOVED INTO DATE FIELD.
H* PSSR CAN DO OUTRAGEOUS THINGS LIKE ENTERING DOW LOOP USING A GOTO
H* Program also performs auto generation of CODE value so that next
H* record gets a code higher by 1 as comared to the previos rec code.
H* -----------------------------------------------------------------
FPFDATE UF A E DISK
FDSDATE CF E WORKSTN
F*
DNODATE S 6S 0 INZ(0)
DNOTIME S 6S 0 INZ(0)
DCD S 4S 0 INZ(0)
C EXSR AUTOGENCODE
C READ BTIME 44
C DOW *IN03 = *OFF
C MOVE NODATE DDATE1
C MOVE NODATE DDATE2
C MOVE NOTIME DTIME1
C MOVE NOTIME DTIME2
C EXFMT RDATE
C MOVE DDATE1 DATE1
C MOVE DDATE2 DATE2
C MOVE DTIME1 TIME1
C MOVE DTIME2 TIME2
C ADD 1 CD
C Z-ADD CD CODE
C WRITE BTIME 77
C UNLOCK PFDATE
C END1 TAG
C ENDDO
C* ---------------------------------------------------
C EVAL *INLR=*ON
C RETURN
C AUTOGENCODE BEGSR
C *HIVAL SETLL BTIME
C READP(N) BTIME 44
C Z-ADD CODE CD
C 1 SETLL BTIME
C ENDSR
C*
C *PSSR BEGSR
C 'PSSR' DSPLY
C DSP_MAJOR DSPLY
C DSP_MINOR DSPLY
C GOTO END1
C ENDSR

Display file DSDATE :

A DSPSIZ(24 80 *DS3)
A CA03(03)
A R RDATE
A 3 14'BOTH DATES AS FOLLOWS :'
A COLOR(WHT)
A DSPATR(UL)

18
RPG-ILE LABS

A 5 14'DATE 1 :'
A 7 14'DATE 2 :'
A 10 14'BOTH TIME VALUES AS FOLLOW
A COLOR(WHT)
A DSPATR(UL)
A 12 15'TIME 1 : '
A 14 15'TIME 2 : '
A DDATE1 6Y 0B 5 25EDTWRD(' - - ')
A EDTMSK(' & & ')
A DDATE2 6Y 0B 7 25EDTWRD(' - - ')
A EDTMSK(' & & ')
A DTIME1 6Y 0B 12 25EDTWRD(' : : ')
A EDTMSK(' & & ')
A DTIME2 6Y 0B 14 25EDTWRD(' : : ')
A EDTMSK(' & & ')

Lisiting if PFDATE :

A R BTIME
A CODE 4S 0
A DATE1 L
A DATE2 L
A TIME1 T
A TIME2 T

Only program is that of control goes into PSSR , I cannot say exactly which MOVE
operation forced it into the PSSR. This way, you canot tell which field to high
light.

LAB : Time and Time stamp validation

Rpgle listing : RPTIME

H TIMFMT(*HMS)
H* -------------------------------------------------------
FDSTIME CF E WORKSTN
DTM1 S T INZ(T'00:00:00')
C* DISPLAY TIME DISPLAY FILE AND INPUT TIME FROM THE USER
C* CHECK IF THIS TIME IS VALID.
C* -------------------------------------------------------
C DOW *IN03 = *OFF
C MOVE *ZEROS DTIMEFLD
C EXFMT RTIME
C *HMS TEST(T) DTIMEFLD 77
C IF *IN77 = *ON
C EVAL *IN77 = *OFF
C 'INCORRECT' DSPLY
C ITER
C ENDIF
C *HMS MOVE DTIMEFLD TM1
C TM1 DSPLY
C ENDDO
C EVAL *INLR = *ON

Display file listing DSTIME :

A DSPSIZ(24 80 *DS3)
A CA03(03)
A R RTIME

19
RPG-ILE LABS

A 4 8'ENTER A TIME VALUE TO BE T


A COLOR(BLU)
A 6 13'===>'
A COLOR(WHT)
A DTIMEFLD 6Y 0B 6 19EDTWRD(' : : ')
A EDTMSK(' & & ')
A COLOR(WHT)
A 7 19'hh mm ss'
A 7 9'Format :-'
A COLOR(BLU)

LAB : Calculate Time difference

H* PROGRAM TO CALCULATE THE TIME DIFFERENCE BETWEEN 2 TIME VALUES.


H* --------------------------------------------------------------
H* Assumes that Factor 1 tim e value is greater than Factor 2 time
H* value.
h* --------------------------------------------------------------
h*
H TIMFMT(*HMS)
DT1 s T INZ(T'07:15:30')
DT2 S T INz(T'10:10:05')
DRslt S T INz(T'00:00:00')
DSEC S 10S 0 INZ(0)
D*
C*
C T2 SUBDUR T1 SEC:*S
C Rslt Adddur sec:*S Rslt
C 'Diff Is : ' DSPLY
C Rslt DSPLY
C EVAL *INLR = *ON
C* Output : 2:54:35

LAB : Read date and time data from PF which stores data as date and time.

Create a PF called PFDAT in QGPL. DDS as follows :

A* DATE AND TIME PROCESSING


A* DATE IS STORED HERE
A* ------------------------
A R RDATE
A BCODE 4S 0
A DISSUE L DATFMT(*DMY)
A DRETURN L DATFMT(*DMY)
A TISSUE T TIMFMT(*HMS)
A TRETURN T TIMFMT(*HMS)

STRSQL and F4 : Specify DATFMT as *DMY and press ENTER.

Use INSERT SQL stmt to insert some sample values into PFDAT.

Create a display file DSDAT with fields : DDISSUE,DDRETURN,DTISSUE, DTRETURN with ‘Y’
as edit code. (created as +9(8) and then edit code Y is applied).

Write following RPDAT program to load the data into RPGLE and display it.

H Datfmt(*DMY/) TimFmt(*HMS:)
FPFdat If E Disk
FDSdat CF E Workstn Display file
c Do 1 fields

20
RPG-ILE LABS

c Read RDate
c DIssue dsply
c* DReturn dsply
c TIssue dsply
c* TReturn dsply
c Movel DIssue DDIssue
c Movel DReturn DDreturn // dont
use EVAL !
c Movel TIssue DTIssue
c Movel TReturn DTReturn
c Exfmt R1
c EndDo
c Eval *inlr = *on

OUTPUT :

DSPLY 24/12/05
DSPLY 09:45:00
Date of issue : 24/12/0500 ___ Display file output
Time of issue : 9/45/0000 ⌡

LAB : Using Date in IF statement.

H Datfmt(*DMY/) TimFmt(*HMS:)
FPFdat If E Disk
c Do 1
c Read RDate
c DIssue dsply
c TIssue dsply
c If DIssue = d'24/12/05'
c '24 DEC 2005' Dsply
c Endif
c EndDo
c Eval *inlr = *on
c Return

LAB : PASS DATE TIME BY Reference to a prceodure

H* PROGRAM TO CALCULATE THE TIME DIFFERENCE BETWEEN 2 TIME VALUES.


H* --------------------------------------------------------------
H* Assumes that Factor 1 tim e value is greater than Factor 2 time
H* value.
h* --------------------------------------------------------------
h*
H TIMFMT(*HMS)
DFind_Difference PR
DT1 T
DT2 T
DRslt T
DT1 s T INZ(T'07:15:30')
DT2 S T INz(T'10:10:05')
DRslt S T INz(T'00:00:00')
D*
C CAllp Find_Difference(T1:T2:Rslt)
C Rslt DSPLY

21
RPG-ILE LABS

C Eval *inlr = *on


C Return
C*
C* -------------------------------------------------------
PFind_Difference B
DFind_Difference PI
DT1 T
DT2 T
DRslt T
DTempTime S T INZ(T'00:00:00')
DSec S 10s 0 inz(0)
C T2 SUBDUR T1 SEC:*S
C TempTime Adddur sec:*S TempTime
C MOVE TempTime Rslt
PFind_Difference E

LAB : *NOPASS FOR PASSING OPTIONAL PARAMATERS

H* PROGRAM TO CALCULATE THE TIME DIFFERENCE BETWEEN 2 TIME VALUES.


H* --------------------------------------------------------------
H* Assumes that Factor 1 tim e value is greater than Factor 2 time
H* value.
h* --------------------------------------------------------------
h*
H TIMFMT(*HMS)
DFind_Difference PR
DT1 T
DT2 T
DRslt T options (*nopass)
DT1 s T INZ(T'07:15:30')
DT2 S T INz(T'10:10:05')
DRslt S T INz(T'00:00:00')
D*
C CAllp Find_Difference(T1:T2:Rslt)
C Rslt DSPLY
C CAllp Find_Difference(T1:T2)
C Eval *inlr = *on
C Return
C*
C* ------------------------------------------------------
PFind_Difference B
DFind_Difference PI

LAB : Accessing Indidator ARRay

dn1 s 4s 0 inz(1)
c Dow n1 < 100
c Eval *in(n1) = *off
c Eval n1 = n1 + 1
c Enddo
c Exsr TestSR
c Eval *inlr = *on
c Return
c* ----------------------------------------
c*
c TestSR Begsr
c Eval *in(45) = *ON
c If *in45 = *on

22
RPG-ILE LABS

c '45 on' Dsply


c Endif
c Eval *in45 = *off
c If *in(45) = *on
c '45 on' Dsply
c Endif
c Endsr

OUTPUT :
Dsply '45 on'

A short cut method to set off all indicators is :

c Eval *in(*) = *off


c Eval *inlr = *on
c Return

DT1 T
DT2 T
DRslt T options(*nopass)
DTempTime S T INZ(T'00:00:00')
DSec S 10s 0 inz(0)
C T2 SUBDUR T1 SEC:*S
C TempTime Adddur sec:*S TempTime
C If %Parms = 3
C MOVE TempTime Rslt
C Return
C Else
C 'No param!' Dsply
c TempTime Dsply
c Endif
PFind_Difference E

After one of the parameters is specified as a nopass parameters, the following


parameters HAVE to be nopass parameters. NOPASS means OPTIONAL.

LAB : Calculate years,months and days between 2 dates :

H* PROGRAM TO CALCULATE THE TIME DIFFERENCE BETWEEN 2 date VALUES.


H* --------------------------------------------------------------
H* Assumes that Factor 1 tim e value is greater than Factor 2 time
H* value.
h* --------------------------------------------------------------
h*
H DATFMT(*DMY)
DDs001 ds
DDys 2s 0 inz(0)
DMnt 2s 0 inz(0)
DYrs 2s 0 inz(0)
DFind_Difference PR
DD1 d
DD2 d
D*---------------------------------------------------
DD1 s D INZ(D'10/01/04')
DD2 S D INz(D'15/01/04')
ddelta s 4s 0 inz(0)
D*
C CAllp Find_Difference(D1:D2)
C Eval *inlr = *on

23
RPG-ILE LABS

C Return
C* -------------------------------------------------------
PFind_Difference B
DFind_Difference PI
DD1 d
DD2 d
C D2 SUBDUR D1 Yrs:*Y
C D1 addDUR Yrs:*Y D1
C D2 SUBDUR D1 Mnt:*M
C D1 addDUR Mnt:*M D1
C D2 SUBDUR D1 Dys:*D
C* ====================================================
c Ds001 dsply
C Return
PFind_Difference E

24
RPG-ILE LABS

LAB : Built-in functions : %TRIM, %SUBSTR, *LEN, %SIZE

%ABS

DA01 S 2P 0 Inz(-1)
DA02 S 10P 3 Inz(-14.567)
C*
C EVAL A01 = %ABS(A01)
C A01 DSPLY
C*
C EVAL A02 = %ABS(A02)
C A02 DSPLY
C*
C EVAL A02 = %ABS(A01 - -2)
C A02 DSPLY
C*
C EVAL *INLR = *ON

%TRIM %EDITC

DNAME S 20A
DDATE S D INZ(D'2003-05-05')
DTIME S T INZ(T'12.12.12')
DRESULT S 10A
DMSG S 50A
DSALARY S 9P 2 INZ(1000)
D*
C EVAL MSG = 'Annual Salary : '
C +%TRIM(%EDITC(Salary*12
C :'A': *CURSYM))
C*
C MSG DSPLY
C DATE DSPLY
C TIME DSPLY
C UDATE DSPLY
C*
C EVAL *INLR = *ON

%SUBSTR

DLEN S 4S 0 INZ(0)
DSTR S 12A INZ('TEST STRING')
C STR DSPLY
C EVAL LEN=%LEN(STR)
C LEN DSPLY
C EVAL STR=%SUBST(STR:2:3)
C STR DSPLY
C SETON LR

OUTPUT : TEST STRING 12 EST

%SIZE

DSTR1 S 14A INZ('TEST STRING')

25
RPG-ILE LABS

DN S 4S 0 INZ(0)
C STR1 DSPLY
C EVAL N=%SIZE(STR1)
C N DSPLY
C SETON LR

Output :
TEST STRING
14

%EDITC

D* Demo of converting Numeric to String.


D* ------------------------------------
Dsal s 5i 0 inz(4000)
Dx s 20a
C eval x=%editc(sal:'A')
C x dsply
C seton lr

LAB : Working on SCAN Opcode and SCAN function

Scan will look for occruance of the sSrc string in the sStr string and write the
position of nSrc (if found in sStr) to nPos.
NPos is zero based so add 1 to nPos. Specify nPos in SubSt() function to get the
rest of the characters after nPos.

dsStr s 12a inz('abc xyz mno')


dsSrc s 1a inz(' ')
dnPos s 4s 0 inz(0)
dsRes s 12a
d*
c sSrc SCAN sStr nPos
c Eval nPos = nPos + 1
c Eval sRes = %SubSt(sStr:nPos)
c sRes Dsply
c* ----------------
c* output : xyz mno
c* ----------------
c Eval *INLR= *ON
c Return

RPGLE program listing : RPSCAN

Arguments to %SCAN :

First arg : String to be searched


Sec Arg : Main string containing the data
Third Arg : START POSITION

dString1 s 10a inz('abcdefghij')


dsrcstr s 1a inz('d')
dLoc s 2s 0 inz(0)
d*
d*-----------------------------------------------------
c Eval Loc = %Scan(srcstr:String1:1)
c 'd loc :' Dsply
c Loc Dsply

26
RPG-ILE LABS

c*
c Eval srcstr = 'b'
c Eval Loc = %Scan(srcstr:String1:3)
c 'b loc :' Dsply
c Loc Dsply
c*
c Eval srcstr = 'x'
c 'x loc :' Dsply
c Eval Loc = %Scan(srcstr:String1:1)
c Loc Dsply
c Eval *inlr = *on

OUTPUT :
DSPLY d loc :
DSPLY 4
DSPLY b loc :
DSPLY 0
DSPLY x loc :
DSPLY 0

27
RPG-ILE LABS

LAB : STRING OPERATIONS : XLATE UPPER CASE TO LOWER CASE

DUC S 26A INZ('ABCDEFGHIJKLMNOPQRSTUVWXYZ')


DLC S 26A INZ('abcdefghijklmnopqrstuvwxyz')
DSTRINP S 7A INZ('ASTRIX')
DSTROUT S 7A
C UC:LC XLATE STRINP STROUT
C STRINP DSPLY
C STROUT DSPLY
C SETON LR

LAB : Special use of CAT

Linkage : RPCAT

CODE :

ds1 s 4a inz('abcd')
ds2 s 4a inz('qrst')
ds3 s 8a
ds4 s 8a
c s1 cat '#':0 s3
c s1 cat '#':2 s4
c s3 Dsply
c s4 Dsply
c* output :
c* abcd#
c* abcd #
c Eval *inlr = *on

PF contents :
---

OUTPUT :

‘#’:2 appends # to the 2nd position after ‘abcd’. Ei at abcdBB#

REMARKS :

‘#’:2  leaves a gap of 2 positions after d of abcd.

28
RPG-ILE LABS

LAB : ARRAY DECLARATION

*************** Beginning of data **********************************


DAR1 S 4S 0 DIM(5)
DN S 4S 0 INZ(1)
C N DOWLT 5
C EVAL AR1(N)=N
C AR1(N) DSPLY
C EVAL N=N+1
C ENDDO
C SETON LR

OUTPUT : 1 2 3 4

H*PRG FOR PRE RUN TIME ARRAY


FPFDEL IT F 25 DISK
D ARR1 S 25 DIM(16) FROMFILE(PFDEL) PERRCD(1)
C MOVEL 'one' VAR 25
C VAR LOOKUP ARR1 35
c*
C *IN35 IFEQ *ON
C 'FOUND' DSPLY
C ELSE
C 'NOT FND' DSPLY
C ENDIF
C ARR1(2) DSPLY
C ARR1(4) DSPLY
C ARR1(12) DSPLY
c*data beyond limit
C ARR1(14) DSPLY
C SETON LR

LAB : COMPILE TIME ARRAY

D ARR S 3 DIM(12) CTDATA PERRCD(6)


C MOVE 'JJL' VAR 3
C VAR LOOKUP ARR 25
C *IN25 IFEQ *ON
C 'FOUND' DSPLY
C ELSE
C 'NOT FND ' DSPLY
C ENDIF
C ARR(2) DSPLY
C ARR(4) DSPLY
C ARR(12) DSPLY
C SETON LR
**
JANFEBMARAPRMAYJUN

29
RPG-ILE LABS

LAB : Compile time table :

LAB : TABLE

DTAB01 S 12A DIM(3) CTDATA ASCEND


DTAB02 S 12S 0 DIM(12) CTDATA ASCEND
D$DATE S 6
D$YY S 2 0
D$MM S 2 0
D$TEMP S 4
D$DD S 2
D$SEP S 1
D$MON S 3
**
JAN
FEB
MAR
APR
MAY
JUN
JUL
AUG
SEP
OCT
NOV
DEC
**
01
02
03
04
05
06
07
08
09
10
11
12

30
RPG-ILE LABS

LAB : ALTERNATE TABLE

DTAB01 S 12A DIM(12) CTDATA PERRCD(2) ASCEND


DTAB02 S 2S 0 ALT(TAB01) DIM(12)
D*
**
01JAN
02FEB
03MAR
04APR
05MAY
06JUN
07JUL
08AUG
09SEP
10OCT
11NOV
12DEC

PRE-RUN TIME TABLE

H*PROGRAM FOR PRE RUN TIME TABLE


F*
FTEST33 IF E DISK
D TABROL S 3 0 DIM(12) EXTFMT(P) FROMFILE(TEST33)
D PERRCD(1)
C*
C Z-ADD 125 VAR 3 0
C VAR LOOKUP TABROL 25
C *IN25 IFEQ *ON
C 'FOUND' DSPLY
C ENDIF
C SETON LR

31
RPG-ILE LABS

LAB : INTRODUCTION TO DATA STRUCTURE AND TYPES OF DATA STRUCTURES

PSDS

D SDS
D PGNAM 1 10
D UNAME 254 263
D DATE 270 275
D TIME 282 287
I*
C* Main Logic
C* ---- -----
C*
C *IN03 DOWEQ *OFF
C*
C MOVEL PGNAM DNAME
C MOVEL UNAME DUNAM
C MOVE DATE DDATE
C MOVE TIME DTIME

MULTI OCCURANCE DS

D JSRDS DS 30 OCCURS(20)
D SCODE 1 5
D SROLL 6 10 0
D SNAME 11 30
C 1 OCCUR JSRDS
C MOVEL 'S001' SCODE
C Z-ADD 1 SROLL
C 2 OCCUR JSRDS
C MOVEL 'S002' SCODE
C Z-ADD 2 SROLL
C MOVEL 'TRIAL' SNAME
C 1 OCCUR JSRDS
C SNAME DSPLY
C SCODE DSPLY
C SROLL DSPLY
C 2 OCCUR JSRDS
C SCODE DSPLY
C SROLL DSPLY
C '---' DSPLY
C JSRDS DSPLY
C SETON LR

DATA AREA DATA STRUCTURE

D JSRDTA UDS
D BCODE 1 4
D BNAME 5 20
C BCODE DSPLY
C BNAME DSPLY
C SETON LR

FILE INFORMATION DATA STRUCTURE :

32
RPG-ILE LABS

FPF001 IF E DISK INFDS(INFDS1)


D INFDS1 DS
D FILE *FILE
D CODE *OPCODE
D STATUS *STATUS
D RECORD *RECORD
D ROUTIN *ROUTINE
C FILE DSPLY
C CODE DSPLY
C STATUS DSPLY
C RECORD DSPLY
C ROUTIN DSPLY
C SETON LR

LAB : INTRODUCTION TO DATA AREAS AND TYPES OF DATA AREAS

Infds :

FTEST1 IF E DISK
FTEST1D UF A E DISK INFDS(STR1)
F INFSR(*PSSR)
D STR1 DS
D STA *STATUS
C READ PFREC1D 26
C Z-ADD 0 VAR 2 0
C READ PFREC 25
C *IN25 DOWEQ *OFF
C Z-ADD NUMBER NUM
C NUM DSPLY
C*
C WRITE PFREC1D
C READ PFREC 25
C ENDDO
C SETON LR
C*
C *PSSR BEGSR
C READ PFREC 25
C ENDSR

NOW IF YOU DO A READ, THE DATA IS TAKEN FROM THE PF AND WRITTEN TO THE FIRST
OCCURANCE OF DS. AND SO ON…

LAB : Error Handling a Multi occurance Data structure

dNOccur s 4s 0 inz(12)
dds001 ds occurs(10)
dN1 4s 0
dN2 4s 0
d**
d sds
dStatus *status
d*
c* specify impossible occurance

33
RPG-ILE LABS

c*
c NOccur Occur ds001 66
c If *in66 = *on
c 'unreachable' dsply
c Status Dsply
c*
c* value of Status will be 122
c*
c EndIf
C Eval *inlr =*on
C Return

PASSING A DS AS A PARAMETER (RPG/400)

RPRCV : RECIEVER PROGRAM LISTING :

IDS001 DS
I 1 40CODE
I 5 14 NAME
C *ENTRY PLIST
C PARM DS001
C NAME DSPLY
C CODE DSPLY
C MOVEL'XML' NAME
C Z-ADD22 CODE
C SETON LR
C RETRN

RPSENDER : CALLING PROGRAM

IDS001 DS
I 1 40CODE
I 5 14 NAME
C Z-ADD12 CODE
C MOVEL'SAM' NAME
C CALL 'RPRCV'
C PARM DS001
C 'PARENT' DSPLY
C NAME DSPLY
C CODE DSPLY
C SETON LR
C RETRN

LAB : Demo of OVERLAY and Multi occurance.


Linkage : RPOVR.

CODE :

* _____________________________________________________
* RPOVR.
* Demo of overlay and multi occurances of variable being
* overlayed.
* a is broken into 2 sections identified by b and c
* There are 10 instances of a , so there are 10 inst of b and c
*
* ########## <-- a(1)
* -----~~~~~
* b(1) c(1)

34
RPG-ILE LABS

* _____________________________________________________
dds001 ds
da 10a Dim(10)
db 5a overlay(a)
dc 5a overlay(a:6)
dcount s 2s 0 inz(1)
dtemp s 5
dabc s 2
c*
c Dow count<4
c* conv to character
c Movel count abc
c 'ABC' cat abc temp
c* ABC01...
c Eval b(count) = temp
c 'xyz' cat abc temp
c* xyz01...
c Eval c(count) = temp
c a(count) dsply
c* ABC01xyz01 ...
c Eval count = count + 1
c End
c Eval *inlr = *on

PF contents :

nil

OUTPUT :

DSPLY ABC01xyz01
DSPLY ABC02xyz02
DSPLY ABC03xyz03

REMARKS :

Overlay can access sections of a variable

LAB : MULTI OCCURANCE EXTERNALLY DESCRIBED DS

CREATE EXTDS : A TYPICAL BCODE, BNAME BPRICE PHYSICAL FILE WITH RECORD SIZE 21
CREATE DDS, COMPILE AND WRITE 5-6 RECORDS TO THE SAME.

DECLARING A EXTERNALLY DESCRIBED DS :

Prompt type . . . DS Sequence number . . . 0001.00

Data Struct External


Name Number Option DS File Name Occurs Length
DS001 E I DS EXTDS 4 21

FEXTDS IF E DISK
IDS001 EIDSEXTDS 4 21
C 1 OCUR DS001
C READ BM 55
C DS001 DSPLY
C 2 OCUR DS001
C READ BM 55

35
RPG-ILE LABS

C DS001 DSPLY
C 1 OCUR DS001
C DS001 DSPLY
C SETON LR

1 OCCUR DS001 SETS THE FIRST OCCURANCE OF DS AS CURRENT OCCURANCE.

LAB : External data structure Example 1

DMYDS E DS EXTNAME(BM001) Occurs(4)


c Eval Bcode = 1
c 1 Occur MyDS
C BCODE Dsply
c 3 Occur MyDS
c Eval Bcode = 12
C BCode Dsply
C Eval *INLR = *ON
C Return

LAB : External data structure : Example 2.

FBM001 if e Disk
DMYDS E DS EXTNAME(BM001) Occurs(4)
c Read BM
C* --------------------------------------------
C* The READ opcode copies the data read from
C* PF into the current occurance of the DS.
C* --------------------------------------------
c 1 Occur MyDS

C BCODE Dsply
C BNAME Dsply
C BPRICE Dsply
c 2 Occur MyDS
c Read BM
C BCODE Dsply
C BNAME Dsply
C BPRICE Dsply
C Eval *INLR = *ON

* END *

36
RPG-ILE LABS

37
RPG-ILE LABS

38
RPG-ILE LABS

LAB : LDA

Lda :

FD002 CF E WORKSTN
C *IN03 DOWEQ *OFF
C *DTAARA DEFINE *LDA CYNAM 10
C IN CYNAM
C CLEAR CYNAM
C MOVE 'test st' CYNAM
C OUT CYNAM
C MOVEL CYNAM DCYNAM
C EXFMT DATA
C ENDDO
C MOVE *ON *INLR
C SETON LR

User defined DATA AREA :

FD001 CF E WORKSTN
C *IN03 DOWEQ *OFF
C *DTAARA DEFINE EMPN 5 0
C IN EMPN
C Z-ADD EMPN DEMPNO
C EXFMT DATA
C *IN03 IFEQ *ON
C LEAVE
C ENDIF
C ENDDO
C MOVE *ON *INLR

LAB : Implementing a dataarea

Create a dataarea called “JSRDTA” fo the type *CHAR and length 10.

Listing :

dDta1 s 10a dtaara(jsrdta)


dtemp s 10a
c *Lock IN Dta1
c Dta1 Dsply
c Movel Dta1 temp
c Clear Dta1
c movel 'new data' dta1
c Out Dta1
c Unlock Dta1
c Eval *inlr = *on

SIGNIFICANCE OF LOCKING THE DATA AREA :

NOTE : If you do not lock the data area during the IN operation, you cannot
UPDATE (ie Change) its contents. You can then only read the data area.

LAB : Handling a locked data area

Listing of CLDTAARA2 :

39
RPG-ILE LABS

Pgm
ALCOBJ OBJ((QGPL/MYDTA *DTAARA *excl)) WAIT(0)
monmsg msgid(CPF1002) exec(goto end1)
CHGDTAARA DTAARA(QGPL/MYDTA) VALUE('sec')
SNDPGMMSG MSG('hi2!') TOPGMQ(*EXT) MSGTYPE(*INQ)
DLCOBJ OBJ((QGPL/MYDTA *DTAARA *excl))
goto end
END1: SNDPGMMSG MSG('cannot allocate')
end: Endpgm

LISTING OF CLDTAARA1 :

Pgm
ALCOBJ OBJ((QGPL/MYDTA *DTAARA *excl)) WAIT(0)
monmsg msgid(CPF1002) exec(goto end1)
/* cannot alocate since it is already locked. */
CHGDTAARA DTAARA(QGPL/MYDTA) VALUE('FIRST')
SNDPGMMSG MSG('hi !') TOPGMQ(*EXT) MSGTYPE(*INQ)
DLCOBJ OBJ((QGPL/MYDTA *DTAARA *excl))
goto end
END1: SNDPGMMSG MSG('cannot allocate')

LAB : Opening file under User Control. (UC).

FPF001 IF E DISK USROPN


C OPEN PF001
C READ BM 77
C BCODE DSPLY
C SETON LR

LAB : Ending a program without setting on LR causes files to remain open

RPPARENT

c 'Parent go:' dsply


c Call 'RPCHILD'
c 'Parent Bk' Dsply
c*
c* do a shift + esc
c* notice that the file PFBMAST
c* is not closed
c* although Child has ended
c* Use RCLRSC from command line
c* to close the PFBMAST file
c*
c Eval *inlr = *on
c Return

RPCHILD

fpfbmast if e disk
c Read bm 88
c 'child!' dsply
c Eval *in44 = *off
c 44 Eval *inlr = *on

40
RPG-ILE LABS

c Return
c

Child does not allow the SETON LR to take place. Result is that child returns without
Closing the PFBMAST file. This can be confirmed by Shift + Esc and 14 to see open files.

LAB : Handling database errors. PSSR, INFSR.INFDS.

FTEST1 IF E DISK
FTEST1D UF A E DISK INFDS(STR1)
F INFSR(*PSSR)
D STR1 DS
D STA *STATUS
C READ PFREC1D 26
C Z-ADD 0 VAR 2 0
C READ PFREC 25
C *IN25 DOWEQ *OFF
C Z-ADD NUMBER NUM
C NUM DSPLY
C* ---------------------------------------------------------------------
C WRITE PFREC1D
C READ PFREC 25
C ENDDO
C SETON LR
C* ---------------------------------------------------------------------
C *PSSR BEGSR
C READ PFREC 25
C ENDSR
C* ---------------------------------------------------------------------

41
RPG-ILE LABS

Lab : I specs

Program described files.

In this lab we look at creating a flat physical file and access the same from a RPGLE
program. The program breaks the row from the flat physical file into sections as
required and assigns that data to variable. This happens for every read operation.

Step1 : Create a flat physical file.


PFFLAT : Record size : 21.

FPfFlat IF F 21 Disk

IPfFlat XX
I 1 4 0cd
I 5 14 nm
I 15 21 2pr
I* First I line is by PI. Second by PJ.

C read pfFlat
C cd dsply
C nm dsply
C pr dsply

C Eval *inlr = *on

The shaded I spec portion indicates the sections of the input record and variables to
which those sections will be assigned.
For each read operation, 1 row is read from the physical file. It is read as 1 single
row of 21 positions. However, in the program, the row is split up and different
sections of the same are assigned to different variables suc as cd,nm and pr as in
above case. CD gets data abetween positions 1 and 4. Same for nm and pr.
Thus although data, while reading is un-structured, it is bifercated into different
sections and used as required in the program.
Data read from physical file :

0001ACAD 0000120

after data is interpreted by I specs :

0001 ACAD 0000120


↓ ↓ ↓
cd nm pr

1..4 5..14 14..21

To the read opcode, we pass the PFFLAT as the record format since flat physical file
has same name for file and record format.

42
RPG-ILE LABS

LAB : O Specs

FPfFlat o F 21 Disk
dcd s 4s 0 inz(108)
dnm s 10a inz('Physics')
dpr s 7s 2 inz(100.25)
c Except e1
C Eval *inlr = *on
oPFFLAT e e1
o cd 4
o nm 14
o pr 21

The first O-spec line :

Prompt type . . . O Sequence number . . . 0014.00

Filename Type Fetch N01N02N03 EXCEPTName


PFFLAT e e1

---- Space ----- ----- Skip -----


Before After Before After Comment
______ ______ ______ _____ __________________

OUTPUT :

108 PHYSICS 10025

above record is added to the physical file.

LAB : O Specs

FPfFlat o F 21 Disk
dcd s 4s 0 inz(108)
dnm s 10a inz('Physics')
dpr s 7s 2 inz(100.25)
c Except e1
c Except e2
C Eval *inlr = *on
oPFFLAT e e1
o cd 4
o nm 14
o pr 21
o e e2
o 14 '** ERROR ** '

In above case, the string ‘ ** ERROR * *’ is inserted into the physical file. It is
placed from the beginning of the record, so some part of the same appears in the
BCode column while some in BName column. (!!)

43
RPG-ILE LABS

44
RPG-ILE LABS

LAB : Declaration of sub files. (rest pf the code is same,no need to cover all
that )

FDSP1 CF E WORKSTN
F SFILE(SFLDATA:RRN)

LAB : Updating file records under Commitment control. Selecting


the correct lock type.

FPF001 UF E DISK COMMIT usropn


C OPEN PF001
C READ BM 77
C BCODE DSPLY
C UPDATE BM
C CLOSE PF001
C SETON LR

LAB : Database basics : How access is done when you try to get a non-keyed access to
a LF which has a K on a certain field.

Database files : PFBMK : typical book master file. LFBMK : Typical book master based
on pfbmk and keys on BPRICE.

Linkage : RPREAD

CODE :

FLfbmk IF E Disk
c 5 setll bm
c Read bm
c bcode dsply
c bprice dsply
c
c Eval *inlr=*on
c Return

PF contents : LFBMK

BCODE BNAME BPRICE


1 ACAD 120.00
2 C 220.00
3 C++ 320.00
4 PAS 120.00
5 COB 220.00
6 AI 430.00
7 HISTORY 100.00
8 ENGLISH 120.00
9 HINDI 90.00
10 MARATHI 75.00
11 Pascal 120.00
12 Cobol 220.00
13 C++ 420.00
14 RPG 2,420.00
15 CL 420.00
16 DB2 520.00
17 ILE 220.00

45
RPG-ILE LABS

OUTPUT :

5
220.00

REMARKS :

Even if it is a keyed file, here we access it in sequential fashion. SETLL has 5 in


factor 1. This gives access to the 5th from top record.

The records are not even arranged in asc order of BPRICE.

LAB : Access LFBMK in keyed fashion.

Linkage : RPREAD1

CODE :

FLfbmk IF E k Disk
dsrc s 7p 2 inz(320)
c src setll bm
c Read bm
c bcode dsply
c bprice dsply
c Eval src = 90
c*
c* SETLL starts searching from the top of the Database file.
c* Record with BPRICE=90 comes way before rec with BPRICE=320
c src setll bm
c Read bm
c bcode dsply
c bprice dsply
c Eval *inlr=*on
c Return

PF contents :

Same as prev lab.

OUTPUT :

DSPLY 3
DSPLY 32000
DSPLY 9
DSPLY 9000

REMARKS :

SETLL starts searching from the top.

LAB : Too less and too large values to setll.

Linkage : RPREAD2

CODE :

FLfbmk IF E k Disk

46
RPG-ILE LABS

dsrc s 7p 2 inz(20)
D*
c* Too less. No rec has bprice = 20. The least value=75.
c*
c src setll bm 444546
c *in44 dsply
c *in45 dsply
c *in46 dsply
c Setoff 444546
c Read bm
c bcode dsply
c bprice dsply
c Eval src = 3000
c*
c* Too large value. No record has bprice = 3000.Largest val is 2,400
c*
c src setll bm 444546
c *in44 dsply
c *in45 dsply
c *in46 dsply
c Setoff 444546
c Read bm
c bcode dsply
c bprice dsply
c Eval *inlr=*on
c Return

PF contents :

Same as prev.

OUTPUT :

DSPLY 0
DSPLY 0
DSPLY 0
DSPLY 10  at the first record.
DSPLY 7500
DSPLY 1  too high a value.
DSPLY 0
DSPLY 0
DSPLY 10  still at the first record.
DSPLY 7500
REMARKS :

47
RPG-ILE LABS

LAB : Behavior of SETLL.

Linkage : RPREAD2

CODE :

FLfbmk IF E k Disk
dsrc s 7p 2 inz(420)
D*
c src setll bm 444546
c *in44 dsply
c *in45 dsply
c *in46 dsply
c Setoff 444546
c Eval src=20
c* Too less. No rec has bprice = 20. The least value=75.
c*
c src setll bm 444546
c *in44 dsply
c *in45 dsply
c *in46 dsply
c Setoff 444546
c Read bm
c bcode dsply
c bprice dsply
c Eval src = 3000
c*
c* Too large value. No record has bprice = 3000
c*
c src setll bm 444546
c *in44 dsply
c *in45 dsply
c *in46 dsply
c Setoff 444546
c Read bm
c bcode dsply
c bprice dsply
c Eval *inlr=*on
c Return

PF contents :

OUTPUT :

DSPLY 0
DSPLY 0
DSPLY 1
DSPLY 0
DSPLY 0
DSPLY 0
DSPLY 10
DSPLY 7500
DSPLY 1
DSPLY 0
DSPLY 0
DSPLY 10
DSPLY 7500

48
RPG-ILE LABS

REMARKS :

To start with, 420 is passed as search argument to setll. SETLL finds an exact match
so the file pointer is positioned to that record and EQ indicator is set on (*in46
= *ON) . So we get 0 0 1 as the output. Next we put 20 as factor-one to setll. There
is no record with this value of bprice. The rec with the least bprice value is 75
which is the first record. Hence file pointer is positioned to the first record and
this is read. No indicator is changed.SETLL does not complain.

So output : 0 0 0 10 75

Next we put 3000 as factor 1 argument to SETLL which is too high. The rec with
largest BPRICE value is 2,400. Hence file pointer is not moved at all and HI
indicator is set on.

Hence Output : 1 0 0 10 75

49
RPG-ILE LABS

LAB : Working on CHAIN, READE

Linkage : RPREAD3

CODE :

FLfbmk IF E k Disk
dsrc s 7p 2 inz(120)
D*
c src chain bm
c Dow Not %EOF
c BCode dsply
c BPrice dsply
c src ReadE bm
c EndDo
c Eval *inlr=*on
c Return

PF contents :

The contents are re-ordered in ascending order of bprice.


Thus the file will NOT be read in the followign order.

BCODE BNAME BPRICE


1 ACAD 120.00
2 C 220.00
3 C++ 320.00
4 PAS 120.00
5 COB 220.00
6 AI 430.00
7 HISTORY 100.00
8 ENGLISH 120.00
9 HINDI 90.00
10 MARATHI 75.00
11 Pascal 120.00
12 Cobol 220.00
13 C++ 420.00
14 RPG 2,420.00
15 CL 420.00
16 DB2 520.00
17 ILE 220.00

OUTPUT :

DSPLY 1
DSPLY 12000
DSPLY 4
DSPLY 12000
DSPLY 8
DSPLY 12000
DSPLY 11
DSPLY 12000

REMARKS :

First CHAIN locates the first record from top. Remaining records with same bprice can
be located using READE.

50
RPG-ILE LABS

LAB : Single page subfile KEYED access to LFBMK

LFBMK : Logical file.

Linkage : RPLFBMK, DSLFBMK.

CODE :

DSLFBMK :

A DSPSIZ(24 80 *DS3)
A PAGEUP(25)
A PAGEDOWN(26)
A R SFLDT SFL
A DCODE 4 0B 5 10COLOR(WHT)
A DNAME 20 B 5 21COLOR(WHT)
A DPRICE 7 2B 5 49EDTWRD(' . ')
A COLOR(WHT)
A 5 61'Rs'
A R SFLCTL SFLCTL(SFLDT)
A CA03(03)
A 50 SFLDSP
A 51 SFLDSPCTL
A 52 SFLCLR
A SFLSIZ(0005)
A SFLPAG(0004)
A 1 23'Book Master Record'
A COLOR(WHT)
A 3 10'Code'
A COLOR(WHT)
A 3 28'Name'
A COLOR(WHT)
A 3 53'Price'
A COLOR(WHT)

RPSFLK :

F*
FLfbmk IF E k Disk
Fdslfbmk CF E Workstn sfile(sfldt:rrn)
drrn s 4s 0 inz(0)
D*
C*
c Exsr CLRSR
c ExSR LDSR
c Dow *in03 = *off
c ExSR DspSR
c ExSR UsrSR
c EndDO
c Eval *inlr = *on
c Return
c*
c UsrSR BegSR
c* Pg up
c If *in25 = *on
c Eval *in25 = *Off
c*
c* go back 8 records.
c*
c do 8

51
RPG-ILE LABS

c ReadP bm
c if %EOF(lfbmk)
c Leave
c EndIf
c EndDo
c EndIf
c* end of PG UP
c* Pg Dn
c If *in26 = *on
c Eval *in26 = *Off
c EndIf
c*
c* In either case,Load is necessary.
c*
c Exsr LDSR
c EndSr
c*
c ClrSR BegSR
c Eval rrn = 0
c Eval *in52 = *on
c Write SflCtl
c Eval *in52 = *off
c EndSR
c*
c LdSR BegSR
c Exsr ClrSR
c*
c* load next 4 records to subfile
c*
c Read bm
c Do 4
c*
c if %EOF
c Leave
c EndIf
c*
c Eval DCode = BCode
c Eval DName = BName
c Eval DPrice = BPrice
c Eval rrn = rrn + 1
c Write SFLDT
c Read bm
c EndDO
c EndSR
c*
c DspSR BegSR
c Eval *in50 = *on
c Eval *in51 = *on
c Exfmt SflCTL
c Eval *in51 = *off
c Eval *in50 = *off
c EndSR

PF contents :

Logical file : Book Master. Keyes on BPRICE.

OUTPUT :

52
RPG-ILE LABS

The records are displayed in single page subfile in ascending order of Bprice.

REMARKS :

Algorithm changes since the access is keyed.

53
RPG-ILE LABS

LAB : Introduction to logic cycle : Default program processing


algorithm.

FPFBM IP F 21 DISK
FQPRINT O F 80 PRINTER OFLIND(*IN20)
IPFBM AA
I 1 4 0CODE
I 5 14 NAME
I 15 21 2PRICE
C 20 SETOFF 20
OQPRINT H 1P 1 1
O 40 '<TITLE COMES HERE>'
O D 1 1
O CODE Z 10
O NAME 30
O PRICE Q 60
O T 20 1 1
O 78 '------------------'

ONE MORE EXAMPLE :

FQPRINT O F 80 PRINTER OFLIND(*IN20)


C N40 Z-ADD *ZEROS CODE 4 0
C SETON 40
C ADD 1 CODE
C 20 SETOFF 20
C CODE IFGT 100
C SETON LR
C ENDIF
C*
OQPRINT H 1P 1 1
O 40 '<TITLE COMES HERE>'
O D 1 1
O CODE Z 10
O T 20 1 1
O 78 '------------------'

USING OVERFLOW IND :

FPFLGC IP F 63 DISK
F*
FQPRINT O F 132 PRINTER OFLIND(*INOF)

LAB : SPECIFY OVERFLOW LINE NUMBER AND NUMBER OF LINES ON THE FORM

ILE CODE :
RUN THIS PROGRAM AND SEE THE NUMBER OF PAGES OF OUTPUT CREATED.

FPFBM IP F 21 DISK
FQPRINT O F 80 PRINTER OFLIND(*IN20) FORMLEN(10) FORMOFL(09)
IPFBM AA
I 1 4 0CODE
I 5 14 NAME
I 15 21 2PRICE
C 20 SETOFF 20
OQPRINT H 1P 1 1
O 40 '<TITLE COMES HERE>'
O D 1 1

54
RPG-ILE LABS

O CODE Z 10
O NAME 30
O PRICE Q 60
O T 20 1 1
O 78 '------------------'

RPG/400 CODE :
L – SPECS ARE USED AS UNDER :

Prompt type . . . L Sequence number . . . 0000.03

Line Form Overflow Overflow


Filename Number Length Line Number Line
QPRINT 20 FL 18 OL

FPFBM IP F 21 DISK
FQPRINT O F 80 20 LPRINTER
LQPRINT 20FL 18OL
IPFBM AA
I 1 40CODE
I 5 14 NAME
I 15 212PRICE
C 20 SETOF 20
OQPRINT H 11 1P
O 40 '<TITLE COMES HERE>'
O D 11
O CODE Z 10
O NAME 30
O PRICE Q 60
O T 11 20
O 78 '------------------'

LAB : Basic Logic Cycle with L1 indicator.

F* BIOPF2 CONTAINS 4 FIELDS.


F* BCODE1 AND BCODE2 HAVE L2 AND L1 INDICATORS
F* ON THEM. L1 IS SET ON EVERTIME BCODE2 CHANGES
F* L2 IS SETON WHEN BCODE1 CHANGES.L2 ALSO SETS ON
F* L1 AUTOMATICALLY.
F* ------------------------------------------------
FBIOPF2 IP F 16 DISK
FQSYSPRT O F 132 PRINTER OFLIND(*INOF)
IBIOPF2 AA
I 1 4 BCODE1 L2
I 5 8 BCODE2 L1
I 9 12 0BIN
I 13 16 0BOUT
OQSYSPRT H
O 1P 40 'FIRST PAGE'
O D N1P
O 7 'BC 1 : '
O BCODE1 9
O 16 'BC 2 : '
O BCODE2 19
O 45 'BOOKS IN : '
O BIN 56

55
RPG-ILE LABS

O T L1
O 37 'TOTAL TIME'
O T LR
O 37 'LR IS ON '
O OF '* OVER FLOW *'

LAB : Simple Logic cycle program with L1 control break indicator.


Linkage : RPGLC2 in samlesrc.

CODE : RPLC2

* ____________________________________________________________
* Simple program demonstrating a logic cycle.
* ____________________________________________________________
* Database file contains BCODE BIN and BOUT fields
* which store the qty of books comming in and going out
* along with their codes.
* Objective is to display the total bin and bout for each book.
* ____________________________________________________________
*
FQPRINT O F 80 PRINTER
FPFBIO1 IP F 12 DISK
DTOTBIN S 5I 0 INZ(0)
DTOTBOUT S 5I 0 INZ(0)
iPFBIO1 AA 88
i 1 4 0bcode L1
i 5 8 0bin
i 9 12 0bout
C*
C IF *INL1 AND *IN88
C EVAL TOTBIN = 0
C EVAL TOTBOUT = 0
C ENDIF
C*
C IF *IN88
C EVAL TOTBIN = TOTBIN + BIN
C EVAL TOTBOUT = TOTBOUT + BOUT
C ENDIF
C*
C*____________________________________________
OQPRINT D N1P
O 10 'CODE :'
O BCODE Z 20
O 30 'IN :-'
O BIN Q 40
O 50 'OUT :-'
O BOUT Q 60
O T L1 88 1 1
O '_______________________
O T L1 88 1 1
O 10 'TOTAL IN :'
O TOTBIN 17
O 40 'TOTAL OUT : '
O TOTBOUT 50
O*
O T L1 88 1 1
O '_______________________

56
RPG-ILE LABS

PF contents : PFBIO1

BCODE BIN BOUT


1 10 0
1 0 10
1 10 0
2 10 0
2 0 10
2 10 0
3 10 0
3 0 10
3 10 0

OUTPUT : QPRINT spool file.

CODE : 1 IN :- 10 OUT :-
CODE : 1 IN :- OUT :- 10
CODE : 1 IN :- 10 OUT :-
_________________________
TOTAL IN : 00020 TOTAL OUT : 00010
_________________________
CODE : 2 IN :- 10 OUT :-
CODE : 2 IN :- OUT :- 10
CODE : 2 IN :- 10 OUT :-
_________________________
TOTAL IN : 00020 TOTAL OUT : 00010
_________________________
CODE : 3 IN :- 10 OUT :-
CODE : 3 IN :- OUT :- 10
CODE : 3 IN :- 10 OUT :-

LAB : Working with L1 and L2 indicators.

CODE :RPLC3

* ____________________________________________________________
* DEMONSTRATING L1 AND L2 INDICATORS.
* ____________________________________________________________
* Database file contains SBCODE,BCODE BIN and BOUT fields
* which store the qty of books comming in and going out
* along with their codes AND THE subject code.
* Objective is to display the total bin and bout for each book.
* grouped by BCode and then Grouped by SBCODE (subject code)
* SBCODE : 1 for mechanical Engg.
* BCODE : 1 for the first book in the mech engg book.
* ____________________________________________________________
*
FQPRINT O F 80 PRINTER
FPFBIO3 IP F 16 DISK
DTOTBINSB S 5I 0 INZ(0)
DTOTBOUTSB S 5I 0 INZ(0)
DTOTBIN S 5I 0 INZ(0)
DTOTBOUT S 5I 0 INZ(0)
DTEMP S 4S 0 INZ(0)
iPFBIO3 AA 88
i 1 4 0sbcode L2
i 5 8 0bcode L1

57
RPG-ILE LABS

i 9 12 0bin
i 13 16 0bout
C*
C*
C IF (*INL1 AND *IN88) and (*INL2)
C EVAL TOTBIN = 0
C EVAL TOTBOUT = 0
C EVAL TOTBINSB = 0
C EVAL TOTBOUTSB = 0
C ENDIF
C*
C IF (*INL1 AND *IN88)
C EVAL TOTBIN = 0
C EVAL TOTBOUT = 0
C ENDIF
c*
C IF *IN88
C EVAL TOTBIN = TOTBIN + BIN
C EVAL TOTBOUT = TOTBOUT + BOUT
C EVAL TOTBINSB = TOTBINSB + BIN
C EVAL TOTBOUTSB = TOTBOUTSB + BOUT
C ENDIF
C*
C*____________________________________________
OQPRINT D N1P
O 10 'CODE :'
O BCODE Z 15
O 25 'IN :-'
O BIN Q 30
O 35 'OUT :-'
O BOUT Q 40
O 45 'SBCODE :'
O SBCODE Q 50
O T L1 88 1 1
O '______________________
O T L1 88 1 1
O 10 'TOTAL IN :'
O TOTBIN 17
O 40 'TOTAL OUT : '
O TOTBOUT 50
O*
O T L1 88 1 1
O '___________________
O*
O*
O T L1 88 L2 1 1
O '+ + + + + + + + + +
O T L1 88 L2 1 1
O 17 'GR.TOTL IN:'
O TOTBINSB 17
O 40 'GR. TOTL OUT:'
O TOTBOUTSB 50
O*
O T L1 88 L2 1 1
O '~~~~~~~~~~~~~~~~~~~
O*

PF contents :PFBIO3

58
RPG-ILE LABS

L1 L2
SBCODE BCODE BIN BOUT
1 1 10 0
1 1 0 10
1 1 10 0
1 2 10 0
1 2 0 10
1 2 10 0
1 3 10 0
1 3 0 10
1 3 10 0
2 1 20 0
2 1 0 20
2 1 20 0
2 2 20 0
2 2 0 20
2 2 20 0
2 3 20 0
2 3 0 20
2 3 40 0

OUTPUT :

*...+....1....+....2....+....3....+....4....+....5...
CODE : 1 IN :- 1OUT :- SBCODE : 1
CODE : 1 IN :- OUT :- SBCODE : 1
CODE : 1 IN :- 1OUT :- SBCODE : 1
_________________________
TOTAL IN : 00020 TOTAL OUT : 00010
_________________________
CODE : 2 IN :- 1OUT :- SBCODE : 1
CODE : 2 IN :- OUT :- SBCODE : 1
CODE : 2 IN :- 1OUT :- SBCODE : 1
_________________________
TOTAL IN : 00020 TOTAL OUT : 00010
_________________________
CODE : 3 IN :- 1OUT :- SBCODE : 1
CODE : 3 IN :- OUT :- SBCODE : 1
CODE : 3 IN :- 1OUT :- SBCODE : 1
_________________________

_________________________
TOTAL IN : 00020 TOTAL OUT : 00010
_________________________
+ + + + + + + + + + + +__
GR.TOT00060 GR. TOTL OUT: 00030
~~~~~~~~~~~~~~~~~~~~~~~~~
CODE : 1 IN :- 2OUT :- SBCODE : 2
CODE : 1 IN :- OUT :- SBCODE : 2
CODE : 1 IN :- 2OUT :- SBCODE : 2
_________________________
TOTAL IN : 00040 TOTAL OUT : 00020
_________________________
CODE : 2 IN :- 2OUT :- SBCODE : 2
CODE : 2 IN :- OUT :- SBCODE : 2
CODE : 2 IN :- 2OUT :- SBCODE : 2
_________________________
TOTAL IN : 00040 TOTAL OUT : 00020
_________________________

59
RPG-ILE LABS

CODE : 3 IN :- 2OUT :- SBCODE : 2


CODE : 3 IN :- OUT :- SBCODE : 2
CODE : 3 IN :- 2OUT :- SBCODE : 2

60
RPG-ILE LABS

LAB : Matching record indicator.

CODE :

* ____________________________________________________________
* Demonstrating the M1 AND L1 indicator.
* ____________________________________________________________
* Database file PFBIO1 contains BCODE BIN and BOUT fields
* Database file PFBIO2 contains XBCODE XBIN and XBOUT fields
* which store the qty of books comming in and going out
* along with their codes.
* Objective is to SEE WHAT M1 DOES.
* ____________________________________________________________
*
FQPRINT O F 80 PRINTER
FPFBIO1 IP F 12 DISK
FPFBIO2 IS F 12 DISK
DTOTBIN S 5I 0 INZ(0)
DTOTBOUT S 5I 0 INZ(0)
DXTOTBIN S 5I 0 INZ(0)
DXTOTBOUT S 5I 0 INZ(0)
DTEMP S 4S 0 INZ(0)
iPFBIO1 AA 88
i 1 4 0bcode L1M1
i 5 8 0bin
i 9 12 0bout
I*
iPFBIO2 AA 89
i 1 4 0Xbcode L1M1
i 5 8 0Xbin
i 9 12 0Xbout
C*_________________________________________
C IF *INL1
C EVAL TOTBIN=0
C EVAL XTOTBIN=0
C EVAL TOTBOUT=0
C EVAL XTOTBOUT=0
C ENDIF
C*
C 88 EVAL TOTBIN = TOTBIN + BIN
C 88 EVAL TOTBOUT = TOTBOUT + BOUT
C*
C 89 EVAL TOTBIN = TOTBIN + XBIN
C 89 EVAL TOTBOUT = TOTBOUT + XBOUT
C*_____________________________________________________
OQPRINT D N1P 88
O 10 'CODE :'
O BCODE Z 20
O 30 'IN :-'
O BIN Q 40
O 50 'OUT :-'
O BOUT Q 60
O*** D N1P
O*** 10 '**MR**'
O D N1P 89
O 10 'XCODE :'
O XBCODE Z 20
O 30 'XIN :-'
O XBIN Q 40
O 50 'XOUT :-'

61
RPG-ILE LABS

O XBOUT Q 60
O T L1 1 1
O 20 'TOTBIN :'
O TOTBIN 30
O 50 'TOTBOUT :'
O TOTBOUT 60

PF contents :

PFBIO1 PFBIO2
BCODE BIN BOUT XBCODE XBIN XBOUT
1 10 0 2 50 0
1 0 10 2 50 0
1 10 0 2 50 0
2 10 0 2 50 0
2 0 10 3 50 0
2 10 0 3 50 0
3 10 0 4 50 0
3 0 10 4 50 0
3 10 0
5 200 0
5 0 100

OUTPUT :

CODE : 1 IN :- 10 OUT :-
CODE : 1 IN :- OUT :- 10
CODE : 1 IN :- 10 OUT :-
TOTBIN : 00020 TOTBOUT : 00010
CODE : 2 IN :- 10 OUT :-
CODE : 2 IN :- OUT :- 10
CODE : 2 IN :- 10 OUT :-
XCODE : 2 XIN :- 50 XOUT :-
XCODE : 2 XIN :- 50 XOUT :-
XCODE : 2 XIN :- 50 XOUT :-
XCODE : 2 XIN :- 50 XOUT :-
TOTBIN : 00220 TOTBOUT : 00010
CODE : 3 IN :- 10 OUT :-
CODE : 3 IN :- OUT :- 10
CODE : 3 IN :- 10 OUT :-
XCODE : 3 XIN :- 50 XOUT :-
XCODE : 3 XIN :- 50 XOUT :-
TOTBIN : 00120 TOTBOUT : 00010
XCODE : 4 XIN :- 50 XOUT :-
XCODE : 4 XIN :- 50 XOUT :-
TOTBIN : 00100 TOTBOUT : 00000
CODE : 5 IN :- 200 OUT :-
CODE : 5 IN :- OUT :- 100
TOTBIN : 00200 TOTBOUT : 00100

REMARKS :

The physical files must have data in ascending or descending order. Any deviation
from this causes a run time error. System starts with the physical file and reads
first rec from physical file. It also scans the first record in the secondary file .
If the Bcode values match the MR is set ON. (we applied a M1 on BCode remember ?).
The system starts processing records in primary file till Bcode does not change. Once
the Bcode is found to be different in the subsequent record, system starts reading

62
RPG-ILE LABS

records with the same bcode from the secondary file (if there were no matching
records in the secondary file having this bcode, system will switch ON the L1
indicator and MR will never be ON in the first place)

1. Read records from primary file till bcode changes.


2. If records with the same bcode are present in the secondar file read all those
records in the secondary file.
3. When all records are exhausted in the secondary file, then turn ON L1 and
allow total output.
4. Read next set of records from primary file.However, if secondary file contains
records with bcode less than what primary file has, read records from the
secondary file.
For example in above case, PFBIO1 contains records with bcode as 2,3,4. So
system first reads records with bcode=1 in primary file, then records with
bcode=1 in secondary file, then records with bcode=2 in primary file then the
same records in the seondary file. Then records with bcode=3 in primary and
later in secondary file.

Now instead of returning back to primary file for the next set, the system
reads records with bcode= 4 in the seondary file and then comes back to
primary file to read records with bcode=5.

PFBIO1 PFBIO2
BCODE BIN BOUT XBCODE XBIN XBOUT
1 10 0 2 50 0
1 0 10 2 50 0
1 10 0 2 50 0
2 10 0 2 50 0
2 0 10 3 50 0
2 10 0 3 50 0
3 10 0 4 50 0
3 0 10 4 50 0
3 10 0
5 200 0
5 0 100

LAB : Study of M1 indicator with L1 for control break.

Linkage : RPGLC6

CODE :

* ____________________________________________________________
* Demonstrating the M1 AND L1 indicator.
* ____________________________________________________________
* Database file PFBIO1 contains BCODE BIN and BOUT fields
* Database file PFBIO2 contains XBCODE XBIN and XBOUT fields
* which store the qty of books comming in and going out
* along with their codes.
* Objective is to SEE WHAT M1 DOES.
* ____________________________________________________________

63
RPG-ILE LABS

*
FQPRINT O F 80 PRINTER
FPFBIO3 IP F 16 DISK
FPFBIO4 IS F 16 DISK
DTOTBIN S 5I 0 INZ(0)
DTOTBOUT S 5I 0 INZ(0)
DXTOTBIN S 5I 0 INZ(0)
DXTOTBOUT S 5I 0 INZ(0)
DTEMP S 4S 0 INZ(0)
iPFBIO3 AA 88
i 1 4 0sbcode L1M1
i 5 8 0bcode
i 9 12 0bin
i 13 16 0bout
I*
iPFBIO4 AA 89
i 1 4 0Xsbcode L1M1
i 5 8 0Xbcode
i 9 12 0Xbin
i 13 16 0xbout
C*_________________________________________
C IF *INL1
C EVAL TOTBIN=0
C EVAL XTOTBIN=0
C EVAL TOTBOUT=0
C EVAL XTOTBOUT=0
C ENDIF
C*
C 88 EVAL TOTBIN = TOTBIN + BIN
C 88 EVAL TOTBOUT = TOTBOUT + BOUT
C*
C 89 EVAL TOTBIN = TOTBIN + XBIN
C 89 EVAL TOTBOUT = TOTBOUT + XBOUT
C*_____________________________________________________
OQPRINT D N1P 88
O 10 'CODE :'
O BCODE Z 20
O 30 'IN :-'
O BIN Q 40
O 50 'OUT :-'
O BOUT Q 60
O*** D N1P
O*** 10 '**MR**'
O D N1P 89
O 10 'XCODE :'
O XBCODE Z 20
O 30 'XIN :-'
O XBIN Q 40
O 50 'XOUT :-'
O XBOUT Q 60
O T L1 1 1
O 20 'TOTBIN :'
O TOTBIN 30
O 50 'TOTBOUT :'
O TOTBOUT 60

64
RPG-ILE LABS

PF contents :

PFBIO3 PFBIO4
SBCODE BCODE BIN BOUT XSBCODE XBCODE XBIN XBOUT
1 1 10 0 1 1 100 0
1 1 0 10 1 1 0 100
1 1 10 0 1 1 100 0
1 2 10 0 1 2 100 0
1 2 0 10 1 2 0 100
1 2 10 0 1 2 100 0
1 3 10 0 1 3 100 0
1 3 0 10 1 3 0 100
1 3 10 0 1 3 100 0
2 1 20 0 2 1 200 0
2 1 0 20 2 1 0 200
2 1 20 0 2 1 200 0
2 2 20 0 2 2 200 0
2 2 0 20 2 2 0 200
2 2 20 0 2 2 200 0
2 3 20 0 2 3 200 0
2 3 0 20 2 3 0 200
2 3 20 0 2 3 200 0

OUTPUT :

CODE : 1 IN :- 10 OUT :-
CODE : 1 IN :- OUT :- 10
CODE : 1 IN :- 10 OUT :-
CODE : 2 IN :- 10 OUT :-
CODE : 2 IN :- OUT :- 10
CODE : 2 IN :- 10 OUT :-
CODE : 3 IN :- 10 OUT :-
CODE : 3 IN :- OUT :- 10
CODE : 3 IN :- 10 OUT :-
XCODE : 1 XIN :- 100 XOUT :-
XCODE : 1 XIN :- XOUT :- 100
XCODE : 1 XIN :- 100 XOUT :-
XCODE : 2 XIN :- 100 XOUT :-
XCODE : 2 XIN :- XOUT :- 100
XCODE : 2 XIN :- 100 XOUT :-
XCODE : 3 XIN :- 100 XOUT :-
XCODE : 3 XIN :- XOUT :- 100
XCODE : 3 XIN :- 100 XOUT :-
TOTBIN : 00660 TOTBOUT : 00330
CODE : 1 IN :- 20 OUT :-
CODE : 1 IN :- OUT :- 20
CODE : 1 IN :- 20 OUT :-
CODE : 2 IN :- 20 OUT :-
CODE : 2 IN :- OUT :- 20
CODE : 2 IN :- 20 OUT :-
CODE : 3 IN :- 20 OUT :-
CODE : 3 IN :- OUT :- 20
CODE : 3 IN :- 20 OUT :-
XCODE : 1 XIN :- 200 XOUT :-
XCODE : 1 XIN :- XOUT :- 200

65
RPG-ILE LABS

XCODE : 1 XIN :- 200 XOUT :-


XCODE : 2 XIN :- 200 XOUT :-
XCODE : 2 XIN :- XOUT :- 200
XCODE : 2 XIN :- 200 XOUT :-
XCODE : 3 XIN :- 200 XOUT :-
XCODE : 3 XIN :- XOUT :- 200
XCODE : 3 XIN :- 200 XOUT :-

TOTBIN : 01320 TOTBOUT : 00660

REMARKS :

First all records in the primary file with SBCODE = 1 are processed, then the system
proceeds to process all records in the secondary file with XSBCODE = 1 anf when all
records with sbcode/xsbcode=1 are exhausted, then the subtotal is pronted and
displayed.

66
RPG-ILE LABS

LAB : SUBFILE DECLARATION

FDSP1 CF E WORKSTN
F SFILE(SFLDATA:RRN)

LAB : Full Load subfile

Linkage : rpsub

CODE :

fpfbm if e disk
fdssub cf e workstn sfile(sfldt:rrn)
drrn s 4s 0 inz(0)
c exsr clrsr
c exsr ldsr
c dow *in03 = *off
c exsr DSPSR
c EndDo
c*
c Eval *inlr = *on
c Return
c*
c*
c clrsr Begsr
c Eval *in52 = *on
c Write SFLCTL
c Eval *in52 = *off
c Endsr
c*
c ldsr Begsr
c read bm 55
c Dow *in55=*off
c z-add bcode dcode
c movel bname dname
c z-add bprice dprice
c Eval rrn = rrn + 1
c Write sfldt
c read bm 55
c Enddo
c Endsr
c*
c dspsr Begsr
c Seton 5051
c Exfmt sflctl
c Setoff 5051
c Endsr

DISPLAY FILE : DSSUB


A DSPSIZ(24 80 *DS3)
A R SFLDT SFL
A DCODE 4 0B 4 9COLOR(WHT)
A DNAME 10 B 4 20COLOR(WHT)
A DPRICE 7 2B 4 36EDTWRD(' . ')
A COLOR(WHT)

67
RPG-ILE LABS

A 4 46'Rs'
A R SFLCTL SFLCTL(SFLDT)
A CA03(03)
A 50 SFLDSP
A 51 SFLDSPCTL
A 52 SFLCLR
A SFLSIZ(0005)
A SFLPAG(0004)
A 1 21'Book Master Information Sc
A COLOR(WHT)

PF contents :

PFBM : Bcode, Bname and Bprice containing 12-14 records.

OUTPUT :

The contents displayed in tabular form

REMARKS :

Full Load Technique.

LAB : Single Page subfile.

Linkage : RPSINGLE

CODE : RPSINGLE

FDssingle CF E WORKSTN SFILE(SFLDT:RRN)


FPFBM IF E DISK
Drrn S 5i 0 inz(0)
Drecptr S 5i 0 inz(1)
C EXSR LDSR
C*
C DOW *IN03 = *OFF
C Eval drecptr = recptr
C EXSR DSPSR
c EXSR USRSR
C ENDDO
C*
C EVAL *INLR = *ON
C RETURN
C*
C*________________________________________________
C*
C CLRSR Begsr
c Eval rrn = 0
c Eval *in52 = *on
c Write Sflctl
c Eval *in52 = *off
c EndSR
c*
c LDSR BEGSR
c Exsr CLRSR

68
RPG-ILE LABS

c recptr Setll bm 77
c* If *in77 = *on
c* Eval recptr = recptr -4
c* Eval *in77 = *off
c* recptr Setll bm 77
c* EndIf
c*
c Read bm
c do 4
c Eval dcode = bcode
c Eval dname = bname
c Eval dprice = bprice
c Eval rrn = rrn + 1
c Write SFLDT
c Read bm
c*
c If %eof
c Leave
c Endif
c*
c ENDDO
c*
c ENDSR
c* |~~~~~~~~|
c DSPSR BEGSR
c Eval *in50 = *on
c Eval *in51 = *on
c Exfmt sflctl
c EXSR USRSR
c Eval *in50 = *off
c Eval *in51 = *off
c ENDSR
c*
c USRSR BEGSR
c*
c* in25 = Page Up
c*
c if *in25 = *on
c 'pag up !' dsply
c Eval *in25= *off
c Eval recptr = recptr - 4
c**
c If recptr < 1
c Eval recptr = 1
c EndIf
c**
c EXSR LDSR
c*
c EndIf
c*
c* in26 = Page Down -> Get the next 4 records.
c*
c if *in26 = *on
c 'pag dn !' dsply
c Eval *in26= *off
c Eval recptr = recptr + 4
c**
c EXSR LDSR
c*
c Endif

69
RPG-ILE LABS

c*
c ENDSR

DISPLAY FILE : DSSINGLE


A DSPSIZ(24 80 *DS3)
A CA03(03 'EXIT')
A R SFLDT SFL
A DCODE 4 0B 5 5
A DNAME 20 B 5 20
A DPRICE 7 2B 5 47EDTWRD(' . ')
A R SFLCTL SFLCTL(SFLDT)
A SFLSIZ(0004)
A SFLPAG(0004)
A PAGEUP(25 'up')
A PAGEDOWN(26 'dn')
A 50 SFLDSP
A 51 SFLDSPCTL
A 52 SFLCLR
A 1 25'BOOK MASTER INFORMATION DE
A DSPATR(RI)
A 3 5'CODE NAME
A PRICE'
A COLOR(WHT)
A DSPATR(UL)
A DSPATR(RI)
A 3 56'recptr'
A 3 63':'
A DRECPTR 5 0O 3 66

PF contents :

Typical Bcode,bname,bprice file.

OUTPUT :

Contents of the database file in a tabular form

REMARKS :

Single Page loading technique

LAB : expanding subfile.

Linkage : RPEXP

CODE :

FSUBEXP CF E WORKSTN SFILE(SFLDT:RRN)


FPFBM IF E DISK
drrn s 5i 0 inz(0)
dRecPtr s 5i 0 inz(1)
d*
d*_______________________________________________
C EXSR CLRSR
C EXSR LDSR
C DOW *IN03 = *OFF
C EXSR DspSR

70
RPG-ILE LABS

C EXSR UsrSR
C EndDo
C Eval *INLR = *ON
C Return
C*
C* ________________________________________________
C*
c CLRSR BegSr
c Eval *in52=*on
c Write SFLCTL
c Eval *in52=*off
c EndSR
c*
c*
c LDSR BegSR
c RecPtr Setll BM
c Do 4
c Read BM
c*
c If %eof
c Leave
c EndIf
c*
c Z-add BCode DCode
c Movel BName DName
c Z-add BPrice DPrice
c Eval rrn = rrn + 1
c Write SFLDT
c EndDo
c EndSR
c*
c DspSR BegSR
c Eval drecptr = recptr
c Eval *in50=*on
c Eval *in51=*on
c Exfmt SflCTL
c Eval *in50=*off
c Eval *in51=*off
c EndSr
c*
c*
c*
c UsrSR BegSR
c* check for
c* PageDn (next
c* set)
c If *in26=*on
c Eval *in26=*off
c 'pg dn' Dsply
c Eval RecPtr = RecPtr + 4
c EXSR LDSR
c EndIf
c*
c EndSR

DISPLAY FILE: SUBEXP

A DSPSIZ(24 80 *DS3)
A CA03(03 'exit')
A R SFLDT SFL

71
RPG-ILE LABS

A DCODE 4 0B 8 6COLOR(WHT)
A DNAME 20 B 8 18COLOR(WHT)
A DPRICE 7 2B 8 42EDTWRD(' . ')
A COLOR(WHT)
A 8 52'Rs'
A COLOR(WHT)
A R SFLCTL SFLCTL(SFLDT)
A PAGEDOWN(26 'dn')
A 50 SFLDSP
A 51 SFLDSPCTL
A 52 SFLCLR
A SFLSIZ(0005)
A SFLPAG(0004)
A DRECPTR 4S 0H SFLRCDNBR
A 2 23'expanding subfile demo.'
A 4 24'Book Master Information '
A COLOR(WHT)
A 6 7'Code Name
A rice'
A COLOR(WHT)

PF contents :

Typical book master file.

OUTPUT :

Contents of the Book Master in tabular format.

REMARKS :

Expanding loading technique.

LAB : Data entry subfile.

Linkage : rpdatae

CODE :

RPDATAE

FSUBDATAE CF E WORKSTN SFILE(SFLDT:RRN)


DRRN S 5I 0 INZ(0)
c*
c*
C Exsr INZSR
c Dow *in03=*off
C Exsr DSPSR
C Exsr CHGSR
c EndDO
c*
C Eval *inlr = *on
C Return
C*
C* ============================================
C*
C INZSR Begsr

72
RPG-ILE LABS

C Eval *in52=*on
C Write Sflctl
C Eval *in52=*off
C EndSR
c*
c*____________________________________________
c DSPSR Begsr
c Eval *in50=*on
c Eval *in51=*on
c Exfmt SFLCTL
c Eval *in50=*off
c Eval *in51=*off
c EndSR
c*
c* ___________________________________________
c ChgSR BegSR
c ReadC SFLDT 55
c Dow *in55=*off
c DCode Dsply
c DName Dsply
c ReadC SFLDT 55
c EndDo
c EndSR

Display FILE : SUBDATAE

A DSPSIZ(24 80 *DS3)
A R SFLDT SFL
A DCODE 4 0B 10 3COLOR(RED)
A DNAME 20 B 10 13COLOR(WHT)
A DPRICE 7 2B 10 43EDTWRD(' . ')
A COLOR(WHT)
A 10 54'Rs'
A R SFLCTL SFLCTL(SFLDT)
A CA03(03)
A 50 SFLDSP
A 51 SFLDSPCTL
A 52 SFLINZ
A SFLSIZ(0010)
A SFLPAG(0007)
A 3 25'Data Entry Subfile'
A 6 2'Enter the book details in
A owing table :'
A COLOR(BLU)
A 8 3'CODE NAME
A PRICE'
A COLOR(BLU)

PF contents :

No pf

OUTPUT :

Data entered/changed is displayed by READC.

REMARKS :

73
RPG-ILE LABS

Data Entry can be done.

LAB : Using CHAIN on Subfile.

Display DSUSR :

A DSPSIZ(24 80 *DS3)
A CF05(05)
A R SFLDT SFL
A DCODE 4 0B 6 4COLOR(WHT)
A DNAME 20 B 6 14
A 55 DSPATR(RI)
A DPRICE 7 2B 6 38EDTWRD(' . ')
A COLOR(WHT)
A 6 48'Rs'
A R SFLCTL SFLCTL(SFLDT)
A CA03(03)
A 50 SFLDSP
A 51 SFLDSPCTL
A 52 SFLCLR
A SFLSIZ(0010)
A SFLPAG(0008)
A OVERLAY
A 2 4'Book Master datab
A COLOR(WHT)
A 3 4'_________________
A COLOR(WHT)
A R FOOT
A OVERLAY
A 22 2'F5:'
A 22 6'Remove'
A 22 13'Hilight'

RPUSR :

Fdsusr cf e workstn sfile(sfldt:rrn)


drrn s 4s 0 inz(1)
dtotrec s 4s 0 inz(1)
dtemp s 4s 0 inz(1)
c ExSR SRClr
c Exsr SRLoad
c Dow *in03 = *Off
c Exsr SRUsr
c Exsr SRDsp
c Eval *in55= *off
c EndDo
c Eval *inlr = *on
c Return
c*____________________________________________________
c SRClr BegSR
c Eval *in52 = *on
c Write SFLCTL
c Eval *in52 = *off
c EndSR
c* ___________________________________________________
c SRLoad BegSR
c Do 100

74
RPG-ILE LABS

c Eval DCode = rrn


c Eval DName = 'Abc'
c Eval Dprice = 1.2 * rrn
c Write SFLDT
c Eval rrn = rrn + 1
c Eval totrec = totrec + 1
c EndDO
c EndSR
c*____________________________________________________
c*
c SRDsp BegSR
c Eval *in50 = *on
c Eval *in51 = *on
c write sflctl
c write foot
c Exfmt SflcTL
c Eval *in50 = *off
c Eval *in51 = *off
c EndSR
c*____________________________________________________
c SRUsr BegSR
c Z-add 1 dummy
c Dow dummy = 1
c Readc sfldt
c If %Eof
c Leave
c EndIf
c Eval *in55 = *on
c update sfldt
c EndDo
c*
c* Check if user wants to clear the hi-light
c* User presses F5 to remove all hi-lights.
c*
c Eval *in55 = *off
c If *in05 = *on
c Eval *in05 = *off
c dow temp < totrec
c*
c* Goto the first record of the subfile
c*
c temp Chain sfldt
c Update sfldt
c Eval temp = temp + 1
c Enddo
c EndIf
c EndSR

Remarks : A subfile is displayed. Make changes to 2 rows and press ENTER. A READC
traps the changes and switches ON the DSPATR(RI) indicator for those records. The
records are thus hi-lighted. Press F5 to remove the hi-light. To remove, the system
goes from first recrord of the subfile to the last and does UPDATE for each record
with the DSPATR(RI) indicator being set OFF.
This removes the Hi-light.

LAB : Using SFLNXTCHG to fo what the above lab does.

Display file :

75
RPG-ILE LABS

A DSPSIZ(24 80 *DS3)
A CF05(05)
A R SFLDT SFL
A 77 SFLNXTCHG
A DCODE 4 0B 6 4COLOR(WHT)
A DNAME 20 B 6 14
A 55 DSPATR(RI)
A DPRICE 7 2B 6 38EDTWRD(' . ')
A COLOR(WHT)
A 6 48'Rs'
A R SFLCTL SFLCTL(SFLDT)
A CA03(03)
A 50 SFLDSP
A 51 SFLDSPCTL
A 52 SFLCLR
A SFLSIZ(0010)
A SFLPAG(0008)
A OVERLAY
A 2 4'Book Master datab
A COLOR(WHT)
A 3 4'_________________
A COLOR(WHT)
A R FOOT
A OVERLAY
A 22 2'F5:'
A 22 6'Remove'
A 22 13'Hilight'

RPG :
Fdsusr1 cf e workstn sfile(sfldt:rrn)
drrn s 4s 0 inz(1)
dtotrec s 4s 0 inz(1)
dtemp s 4s 0 inz(1)
c ExSR SRClr
c Exsr SRLoad
c Dow *in03 = *Off
c Exsr SRUsr
c Exsr SRDsp
c Eval *in55= *off
c EndDo
c Eval *inlr = *on
c Return
c*____________________________________________________
c SRClr BegSR
c Eval *in52 = *on
c Write SFLCTL
c Eval *in52 = *off
c EndSR
c* ___________________________________________________
c SRLoad BegSR
c Do 100
c Eval DCode = rrn
c Eval DName = 'Abc'
c Eval Dprice = 1.2 * rrn
c Write SFLDT
c Eval rrn = rrn + 1
c Eval totrec = totrec + 1

76
RPG-ILE LABS

c EndDO
c EndSR
c*____________________________________________________
c*
c SRDsp BegSR
c Eval *in50 = *on
c Eval *in51 = *on
c write sflctl
c write foot
c Exfmt SflcTL
c Eval *in50 = *off
c Eval *in51 = *off
c EndSR
c*____________________________________________________
c SRUsr BegSR
c Z-add 1 dummy
c If *in05 = *off
c Dow dummy = 1
c Readc sfldt
c If %Eof
c Leave
c EndIf
c Eval *in55 = *on
c Eval *in77 = *on
c update sfldt
c Eval *in77 = *off
c EndDo
c EndIF
c*
c* Check if user wants to clear the hi-light
c* User presses F5 to remove all hi-lights.
c*
c Eval *in55 = *off
c If *in05 = *on
c '05 on' dsply
c Z-add 1 dummy
c Dow dummy = 1
c Readc sfldt
c If %Eof
c Leave
c EndIf
c Eval *in55 = *off
c*********** Eval *in77 = *on
c update sfldt
c 'remove' dsply
c EndDo
c Eval *in05 = *off
c EndIF
c EndSR

77
RPG-ILE LABS

LAB : SFLNXTCHG

Linkage : RPSFLNXT,DSSFLNXT

CODE :

FDSSFLNXT CF E WORKSTN SFILE(SFLDT:RRN)


FPFBM IF E DISK
C* Press F6 to see changed records and setof the MDT.
C* Press F10 to see changed records and again SETON the MDT.
C*
C*
drrn s 5i 0 inz(0)
dCNTR s 5i 0 inz(0)
dtemp s 5i 0 inz(1)
dResetMDT s 5i 0 inz(1)
C EXSR CLRSR
C EXSR LDSR
c DoW *in03=*off
c EXSR DSPSR
C EXSR USRSR
C EndDO
C Seton lr
C Return
C*
C*
C Clrsr BegSR
C Eval *in52 = *on
C Write SflCTL
C Eval *in52 = *off
C EndSR
C*
C*
C LDSR BegSR
c Read bm
c Dow Not %EOF
c Eval DCode = BCode
c Eval DName = BName
c Eval DPrice = BPrice
c Eval RRN = RRN + 1
c Eval Cntr = Cntr + 1
c Write SFLDT
c Read bm
c EndDo
c 'RRN :' Dsply
c rrn Dsply
c EndSR
c*
c*
c DspSR BegSR
c Eval *in50=*on
c Eval *in51=*on
c Exfmt SFLCTL
c Eval *in50=*off
c Eval *in51=*off
c EndSR
c*
c*
c UsrSR BegSR

78
RPG-ILE LABS

c IF *in06=*on
c Eval *in06=*off
c Exsr ChgSR1
c EndIf
c*
c IF *in10=*on
c Eval *in10=*off
c EXSR ChgSR2
c EndIF
c ENDSR
c*
c ChgSR1 BegSR
c Readc SFLDT 78
c*
c DoW NOT *in78
c DCode Dsply
c DName Dsply
c* ---------------
c* should we reset
c* the MDT ?
c* ----------------
c If ResetMDT = 1
c Eval *in77=*ON
c* Switch on MDT
c Update SFLDT
c Eval *in77=*OFF
c 'reset !' Dsply
c EndIf
c*
c Readc SFLDT 78
c EndDO
c*
c EndSR
c*
c ChgSR2 BegSR
c eval ResetMDT = 1
c Exsr ChgSR1
c eval ResetMDT = 0
c EndSR

DISPLAY FILE : DSSFLNXT

A DSPSIZ(24 80 *DS3)
A CA03(03)
A CF06(06)
A CF10(10)
A R SFLDT SFL
A 77 SFLNXTCHG
A DCODE 4 0B 8 4COLOR(RED)
A DNAME 20 B 8 21COLOR(WHT)
A DPRICE 7 2B 8 48EDTWRD(' . ')
A COLOR(WHT)
A 8 59'Rs'
A R SFLCTL SFLCTL(SFLDT)
A 50 SFLDSP
A 51 SFLDSPCTL
A 52 SFLCLR
A SFLSIZ(0006)
A SFLPAG(0005)
A 2 18'Demo of SFLNXT Change'

79
RPG-ILE LABS

A 4 4'Make changes to a record,


A ears the MDT but SFLNXTCHG
A ts the '
A COLOR(WHT)
A 5 4'MDT to 1'
A COLOR(WHT)
A 7 4'Code Name
A Price'
A COLOR(WHT)

PF contents :

Typical Book master

OUTPUT :

If 1,2 (or more) records are edited and F6 is pressed, the program shows us the
records that have changed and resets their MDT. Press F6 again has no effect since
the MDT of those records are now reset (ie set to 0).

However, if F10 is pressed, the changed records are displayed but their MDTs are set
back to 1. Pressing F10 again and again will re-display the same set of records since
their MDTs are never set to zero.

REMARKS :

SFLNXT can be user to set ON MDT of a specific record.

LAB : Using CHAIN in subfiles.

Linkage : RPSFLCHAIN

CODE :

FDSSFLchainCF E WORKSTN SFILE(SFLDT:RRN)


FPFBM IF E DISK
c*
C* Study the effect and application of CHAIN on subfile.
C* Access bprice from user. All records with Bprice greater
c* specified are hilighted.
c*
c*
drrn s 5i 0 inz(0)
dtemp s 5i 0 inz(1)
dcntr s 5i 0 inz(1)
C EXSR CLRSR
C EXSR LDSR
c DoW *in03=*off
c EXSR DSPSR
C EXSR USRSR
C EndDO
C Seton lr
C Return
C*
C*
C Clrsr BegSR
C Eval *in52 = *on

80
RPG-ILE LABS

C Write SflCTL
C Eval *in52 = *off
C EndSR
C*
C*
C LDSR BegSR
c Read bm
c Dow Not %EOF
c Eval DCode = BCode
c Eval DName = BName
c Eval DPrice = BPrice
c Eval RRN = RRN + 1
c Eval Cntr = Cntr + 1
c Write SFLDT
c Read bm
c EndDo
c EndSR
c*
c*
c DspSR BegSR
c Eval *in50=*on
c Eval *in51=*on
c Exfmt SFLCTL
c Eval *in50=*off
c Eval *in51=*off
c EndSR
c*
c*
c UsrSR BegSR
c Eval temp=1
c IF *in06=*on
c* ___________________
c*|access each record |
c*|of the subfile. |
c*|if the record has |
c*|bprice greater than|
c*|the one specified, |
c*|Hilight it otherwis|
c*|leave it. |
c*|___________________|
c Dow temp< cntr
c temp Chain SFLDT
c* in77 is for SFLNXTCHG
c*
c if Dprice > DUsrPrc
c Eval *in77 = *ON
c Eval *in88 = *ON
c Update SFLDT
c Eval *in77 = *Off
c Eval *in88 = *Off
c* else !
c else
c Eval *in88 = *off
c Eval *in77 = *on
c Update SFLDT
c Eval *in77 = *off
c*
c EndIf
c Eval temp=temp+1
c EndDo

81
RPG-ILE LABS

c****************** Exsr HiLight


c EndIf
c ENDSR
c HiLight BegSR
c* 88 is for DSPATR(RI)
c*
c Eval *in88 = *on
c Write SFLCTL
c Eval *in88 = *off
c
c EndSR
c*

DISPLAY FILE : DSSFLCHAIN

A DSPSIZ(24 80 *DS3)
A CA03(03)
A CF06(06)
A CF10(10)
A R SFLDT SFL
A 77 SFLNXTCHG
A DCODE 4S 0B 8 4COLOR(RED)
A 88 DSPATR(RI)
A DNAME 20A B 8 21COLOR(WHT)
A 88 DSPATR(RI)
A DPRICE 7Y 2B 8 48EDTWRD(' . ')
A 88 DSPATR(RI)
A COLOR(WHT)
A 8 59'Rs'
A R SFLCTL SFLCTL(SFLDT)
A SFLSIZ(0006)
A SFLPAG(0005)
A 50 SFLDSP
A 51 SFLDSPCTL
A 52 SFLCLR
A 2 18'Demo of SFLNXT Change'
A 7 4'Code Name
A Price'
A COLOR(WHT)
A 4 3'Enter upper limit for book
A '
A COLOR(WHT)
A DUSRPRC 7 2B 4 40EDTWRD(' . ')
A COLOR(RED)
A 6 4'Press F6 to hi-light all r
A ith book prices greater tha
A rice'
A COLOR(TRQ)

PF contents :

Usual PFBM file.

OUTPUT :

Enter a book price in the “Upper Limit” field. And press F6. All records where the
book price is greater than the specified book price are highlighted. Reset of the
records are not highlighted.

82
RPG-ILE LABS

REMARKS :

Principle : Scan each record in the subfile using chain. For each record check if
DPRICE is greater than DUSRPRC (which is user specified price) if DPRICE is larger,
switch on indicators for SFLNXTCHG and DSPATR(RI) and call UPDATE. This maeks the
record active (in77) and hi-lights it (in88). Switch off both indicator. Proceed to
the next record.
In this manner all records are checked and MDT is set on for those who have bprice
greater than specified. Hilighting is done only when SFLNXTCHG is on. If this is
tried at other times, when SFLNXTCHG is off, there will be no effect.

STUDY PROGRAM

For following program displays al records of the Book Master database file.
It accepts book price from user and
Displays all records where book price is 100 greater than specified book price in RI
form.(reverse image)
It displays records where bprice = specified bprice or upto specified bprice + 100 in
Hi intensity (bname comes with a column sperator)

Linkage : RPSFLCHAI1
Display file : DSSFLCHAI1

FDSSFLchai1CF E WORKSTN SFILE(SFLDT:RRN)


FPFBM IF E DISK
c*
C* Study the effect and application of CHAIN on subfile.
C* Access bprice from user. All records with Bprice greater
c* specified are hilighted.
c*
c*
drrn s 5i 0 inz(0)
dtemp s 5i 0 inz(1)
dcntr s 5i 0 inz(1)
C EXSR CLRSR
C EXSR LDSR
c DoW *in03=*off
c EXSR DSPSR
C EXSR USRSR
C EndDO
C Seton lr
C Return
C*
C*
C Clrsr BegSR
C Eval *in52 = *on
C Write SflCTL
C Eval *in52 = *off
C EndSR
C*
C*
C LDSR BegSR
c Read bm
c Dow Not %EOF
c Eval DCode = BCode
c Eval DName = BName

83
RPG-ILE LABS

c Eval DPrice = BPrice


c Eval RRN = RRN + 1
c Eval Cntr = Cntr + 1
c Write SFLDT
c Read bm
c EndDo
c EndSR
c*
c*
c DspSR BegSR
c Eval *in50=*on
c Eval *in51=*on
c Exfmt SFLCTL
c Eval *in50=*off
c Eval *in51=*off
c EndSR
c*
c*
c UsrSR BegSR
c Eval temp=1
c IF *in06=*on
c* ___________________
c*|access each record |
c*|of the subfile. |
c*|if the record has |
c*|bprice greater than|
c*|the one specified, |
c*|Hilight it otherwis|
c*|leave it. |
c*|___________________|
c Dow temp< cntr
c temp Chain SFLDT
c* in77 is for SFLNXTCHG
c*
c if (Dprice - DUsrPrc)> 100
c Eval *in77 = *ON
c Eval *in88 = *ON
c Update SFLDT
c Eval *in77 = *Off
c Eval *in88 = *Off
c Endif
c if (Dprice - DUsrPrc)<=100 and Dprice >=dUsr
c Eval *in77 = *ON
c Eval *in89 = *ON
c Update SFLDT
c Eval *in77 = *Off
c Eval *in89 = *Off
c Endif
c If DPrice < DUsrPrc
c Eval *in88 = *off
c Eval *in89 = *off
c Eval *in77 = *on
c Update SFLDT
c Eval *in77 = *off
c*
c EndIf
c Eval temp=temp+1
c EndDo
c****************** Exsr HiLight
c EndIf

84
RPG-ILE LABS

c ENDSR
c HiLight BegSR
c* 88 is for DSPATR(RI)
c*
c Eval *in88 = *on
c Write SFLCTL
c Eval *in88 = *off
c
c EndSR
c*

DISPLAY FILE :

A DSPSIZ(24 80 *DS3)
A CA03(03)
A CF06(06)
A CF10(10)
A R SFLDT SFL
A 77 SFLNXTCHG
A DCODE 4S 0B 8 4
A 88 DSPATR(RI)
A 89 DSPATR(UL)
A DNAME 20A B 8 21
A 88 DSPATR(RI)
A 89 DSPATR(CS)
A DPRICE 7Y 2B 8 48EDTWRD(' . ')
A 88 DSPATR(RI)
A 89 DSPATR(HI)
A
A 8 59'Rs'
A R SFLCTL SFLCTL(SFLDT)
A SFLSIZ(0006)
A SFLPAG(0005)
A 50 SFLDSP
A 51 SFLDSPCTL
A 52 SFLCLR
A 2 18'Demo of SFLNXT Change'
A 7 4'Code Name
A Price'
A COLOR(WHT)
A 4 3'Enter upper limit for book
A '
A COLOR(WHT)
A DUSRPRC 7 2B 4 40EDTWRD(' . ')
A COLOR(RED)
A 6 4'Press F6 to hi-light all r
A ith book prices greater tha
A rice'
A COLOR(TRQ)

LAB : Multiple active subfiles.

Linkage : rpmulti,dsmulti

CODE :

FDSMULTI CF E WORKSTN SFILE(SFLDT1:RRN1) SFILE(SFLDT2:RRN2)


FPFBM IF E DISK

85
RPG-ILE LABS

FPFBIO IF E DISK Prefix(x)


dRRN1 s 5i 0 inz(0)
dRRN2 s 5i 0 inz(0)
C EXSR CLRSR1
C EXSR CLRSR2
C EXSR LDSR1
C EXSR LDSR2
C DOW *IN03 = *OFF
C EXSR DSPSR1
C EXSR DSPSR2
C ENDDO
C EVAL *inlr = *on
C Return
C CLRSR1 Begsr
C Eval *in52 = *on
C Write SFLCTL1
C Eval *in52 = *off
C EndSR
C*
C*
C CLRSR2 Begsr
C Eval *in62 = *on
C Write SFLCTL2
C Eval *in62 = *off
C EndSR
C
C LDSR1 Begsr
C Read BM
C Dow NOT %EOF
C Eval DCode1 = BCode
C Eval DName = BName
C Eval DPrice = BPrice
C Eval RRN1 = RRN1 + 1
C Write SFLDT1
C Read bm
C EndDo
C EndSR
C*
C LDSR2 Begsr
C Read Bio
C Dow NOT %EOF
C Eval DCode2 = xBCode
C Eval DBin = XBin
C Eval DBout = XBout
C Eval RRN2 = RRN2 + 1
C Write SFLDT2
C Read bio
C EndDo
C EndSR
C*
c DSPSR1 BegSR
c Eval *in51=*on
c Eval *in50=*on
c Exfmt SFLCTL1
c Eval *in50=*off
c Eval *in51=*off
c EndSR
c*
c DSPSR2 BegSR
c Eval *in61=*on

86
RPG-ILE LABS

c Eval *in60=*on
c Exfmt SFLCTL2
c Eval *in60=*off
c Eval *in61=*off
c EndSR

DISPLAY FILE :

A DSPSIZ(24 80 *DS3)
A CA03(03)
A R SFLDT1 SFL
A DCODE1 4 0B 4 5COLOR(WHT)
A DNAME 20 B 4 18COLOR(WHT)
A DPRICE 7 2B 4 43EDTWRD(' . ')
A COLOR(WHT)
A 4 53'Rs'
A R SFLCTL1 SFLCTL(SFLDT1)
A 50 SFLDSP
A 51 SFLDSPCTL
A 52 SFLCLR
A SFLSIZ(0005)
A SFLPAG(0004)
A 1 25'Book Master Information'
A COLOR(WHT)
A 3 6'Code Name
A Price'
A R SFLDT2 SFL
A DCODE2 4 0B 18 10
A DBIN 4 0B 18 22
A DBOUT 4 0B 18 31
A R SFLCTL2 SFLCTL(SFLDT2)
A 60 SFLDSP
A 61 SFLDSPCTL
A 62 SFLCLR
A SFLSIZ(0004)
A SFLPAG(0003)
A OVERLAY
A 14 12'Transaction Details'
A COLOR(RED)
A 16 11'Code IN OUT'
A COLOR(WHT)

PF contents :

PFBM : book master


PFBIO : Book I/O file.

OUTPUT :

Simple displays all records in the respective files in the respective subfiles. It is
a simple display program.

REMARKS :

---

LAB : Cursor location in the subfile. SFLCSRRRN


Linkage : TESTRPG1, TESTSFL

87
RPG-ILE LABS

CODE :

ftestsfl cf e workstn sfile(sfldt:rrn)


drrn s 5i 0 inz(0)
d*
c Exsr clrsr
c Exsr ldsr
c Dow *in03=*off
c exsr dspsr
c* n is declared in display file as a SFLCSRRRN variable.
c n dsply
c EndDo
c Eval *inlr=*on
c Return
c*
c*
c Clrsr BegSR
c Eval *in52=*on
c Write SflCTL
c Eval *in52=*off
c EndSR
c*
c*
c LDSR BegSR
c do 10
c Eval DCode = rrn
c Eval DName = 'aaa'
c Eval DPrice = rrn * 5
c Eval rrn=rrn+1
c Write SFLDT
c Enddo
c EndSR
c*
c DSPSR BegSR
c Eval *in50=*on
c Eval *in51=*on
c Exfmt SflCTL
c Eval *in50=*off
c Eval *in51=*off
c EndSR

DISPLAY FILE :
A DSPSIZ(24 80 *DS3)
A CA03(03)
A R SFLDT SFL
A DCODE 4 0B 6 7
A DNAME 20 B 6 18
A DPRICE 7 2B 6 41EDTWRD(' . ')
A R SFLCTL SFLCTL(SFLDT)
A 50 SFLDSP
A 51 SFLDSPCTL
A 52 SFLCLR
A SFLSIZ(0005)
A SFLPAG(0004)
A SFLCSRRRN(&N)
A N 5S 0H
A 3 7'test subfile'

88
RPG-ILE LABS

PF contents :

nil

OUTPUT :

SFLCSRRRN loads the rrn number of the record where cursor is present into the
supplied variable : N. Thus if cursor is on the second page and second record (and
page size is 5 ) then n=7.

REMARKS :

Can get direct access to exact rrn number of the subfile where the cursor is located.

LAB : Use SFLCRSRRN,SFLRCDNBR to access record positions of a subfile and display


transaction details of book in a transaction file.

Linkage : TESTRPG2,sUBMOD,
Display : TESTSFL

CODE :

TESTRPG2 :
D*
D*
c Callb 'SUBMOD'
c Eval *inlr=*on

SUBMOD :

FTestsfl cf e workstn sfile(sfldt:rrn) sfile(sfldt1:rrn


FPFBM IF E Disk
FPFbio IF E Disk Prefix(x)
drrn s 5i 0 inz(0)
drrn1 s 5i 0 inz(0)
dtemp s 4s 0 inz(0)
d* Procedure prototypes
dclrsr pr
dldsr pr
ddspsr pr
dUsrsr pr
dclrsr1 pr
dldsr1 pr 5i 0
d 4s 0
ddspsr1 pr
dShowSubfile pr
d 4s 0
d* ---------------
d* Main Procedure.
d* ---------------
c Eval drecptr=1
c CAllp clrsr
c Callp ldsr
c Dow *in03=*off
c Callp dspsr
c*
c If *in06=*on

89
RPG-ILE LABS

c Eval *in06=*off
c callp UsrSR
c EndIf
c*
c EndDo
c Eval *inlr=*on
c Return
c*
c* _____________________________________
c*
PClrSR B
dclrsr pi
c Eval *in52=*on
c Write SflCTL
c Eval *in52=*off
PClrSR E
c*
c*
PLdSR B
dLdsr pi
c Read BM
c dow Not %EOF
c Eval DCode = BCode
c Eval DName = BName
c Eval DPrice = BPrice
c Eval rrn = rrn + 1
c Write SFLDT
c Read BM
c Enddo
PLdSR E
c*
c*
PDspSR B
DDspSR PR
c Eval *in50=*on
c Eval *in51=*on
c if n <> 0
c Eval drecptr = n
c EndIf
c Exfmt SflCTL
c Eval *in50=*off
c Eval *in51=*off
PDspSR E
c*
PUsrSR B
DUsrSR PR
dtemp s 4s 0 inz(0)
c* check where the cursor is.
c* if n is zero, cursor is not in the subfile at all.
c* n is a parameter given to SFLCSRRRN in the subfile.
c*
c If n=0
c return
c endIf
c* read the subfile record where cursor is present
c n chain sfldt
c*
c* ------------------------------------------
c* show matching records in the transaction file in a new subfile.
c Eval temp = dcode

90
RPG-ILE LABS

c Callp ShowSubfile(temp)
PUsrSR E
c*
c*===================================================
c* showsubfile displays the second subfile containing
c* matching records from the transaction file.
c*
PShowSubFile B
DShowSubFile PI
dtheCode 4s 0
dretval s 5i 0
c*arg theCode contains the dcode,
c callp clrsr1
c Eval retval = ldsr1(theCode)
c*
c If retval =-1
c* no records were loaded !!!
c 'no records !'dsply
c return
c EndIf
c*
c callp dspsr1
c return
PShowSubFile e
PClrsr1 b
dClrsr1 PI
c Eval rrn1=0
c Eval *in62=*on
c Write sflctl1
c Eval *in62=*off
PClrsr1 e
c*
PLdsr1 b
dLdsr1 PI 5i 0
dbkcode 4s 0
dretval s 5i 0
c 'filter :' dsply
c bkcode dsply
c Eval rrn1 = 0
c 1 Setll bio
c Read bio
c Dow Not %EOF
c*
c* pickup only records where bcode matches
c If xBCode = bkcode
c Eval DCode1 = xBCode
c Eval DBin = xBin
c Eval DBout = xBout
c Eval RRN1 = RRN1 +1
c write Sfldt1
c EndIf
c Read bio
c Enddo
c If rrn1=0
c* No records where loaded!!!
c 'no rec !' dsply
c Eval retval=-1
c return retval
c else
c Eval retval=1

91
RPG-ILE LABS

c return retval
c
c EndIf
PLdsr1 E
PDspSR1 B
c Eval *in60 = *On
c Eval *in61 = *On
c Exfmt Sflctl1
c Eval *in60 = *Off
c Eval *in61 = *Off
PDspSR1 E

DISPLAY FILE :

A DSPSIZ(24 80 *DS3)
A CA03(03)
A CF06(06)
A R SFLDT SFL
A DCODE 4 0B 6 7
A DNAME 20 B 6 18
A DPRICE 7 2B 6 41EDTWRD(' . ')
A R SFLCTL SFLCTL(SFLDT)
A SFLSIZ(0005)
A SFLPAG(0004)
A 50 SFLDSP
A 51 SFLDSPCTL
A 52 SFLCLR
A SFLCSRRRN(&N)
A DRECPTR 4S 0H SFLRCDNBR
A N 5S 0H
A 4 57'F6 : lookup Transaction'
A COLOR(BLU)
A 1 9'Book Master Records'
A COLOR(RED)
A R SFLDT1 SFL
A DCODE1 4S 0B 17 10
A DBIN 4S 0B 17 20
A DBOUT 4S 0B 17 29
A R SFLCTL1 SFLCTL(SFLDT1)
A 60 SFLDSP
A 61 SFLDSPCTL
A 62 SFLCLR
A SFLSIZ(0005)
A SFLPAG(0004)
A OVERLAY
A 15 23'Transaction Details...'
A COLOR(RED)
A DSPATR(UL)

PF contents :

Frist subfile displays all records of the PFBM. Second subfile displays select
records from PFBIO. The selection criteria comes from the frist subfile. Use will
place cursor on a record and press F6. The dcode at the cursor location is scanned
and transaction records related to that bcode are loaded into the second subfile that
is displayed.

OUTPUT :

92
RPG-ILE LABS

All contents of Book master, select contents of BIO table.


(PFBM and PFBIO are accessed)

REMARKS :

---

LAB : Window Subfile

Linkage : DSWINSFL

LAB : Window Subfile.

Linkage :

CODE :

A DSPSIZ(24 80 *DS3)
A CA03(03)
A R SFLDT SFL
A DCODE 4 0B 7 10COLOR(RED)
A DNAME 20 B 7 19COLOR(WHT)
A DPRICE 7 2B 7 33EDTWRD(' . ')
A COLOR(WHT)
A 7 43'Rs'
A R SFLCTL SFLCTL(SFLDT)
A 50 SFLDSP
A 51 SFLDSPCTL
A 52 SFLCLR
A SFLSIZ(0011)
A SFLPAG(0007) .

A WINDOW(2 2 16 60)
A OVERLAY
A 4 18'Subfile Test'
A COLOR(WHT)
A 6 10'Code'
A COLOR(WHT)
A 6 20'Name'
A COLOR(WHT)
A 6 34'Price'
A COLOR(WHT)

Subfile code for RPG remains the same.

PF contents :

OUTPUT :

REMARKS :

93
RPG-ILE LABS

LAB : Introduction to Triggers. Database Trigger programming.

STRUCTURE OF STUDENT MASTER (SM) PF :

A R SMAS
A SROLL 4S 0
A SNAME 10A
CAUTION :
FOLLOWING PROGRAM GIVES INCORRECT RESULTS FOR

C EVAL VCD2=%TRIM(%SUBST(VCD1:NOFF:4))

SUITABLE FUNCTION TO CONVERT THE CHARECTER REPRESENTATION OF A STRING INTO NUMERIC IS REQUIRED.

REST OF THE PROGRAM GIVES THE DATA IN THE RECORD SEND BY THE DB ENGINE TO THIS PROGRAM VIA
COMMAND LINE ARGUMENTS.

DPARM1 DS 130
DNOFF 65 68B 0
DPARM2 DS
DLENG 1 40
DLEN1 S 4S 0
DVCD1 S 130A
DVCD2 S 10A
DROLLNO S 4F
D* ___________________________________________________
C *ENTRY PLIST
C PARM1 PARM PARM1
C PARM2 PARM PARM2
C NOFF DSPLY
C*
C EVAL VCD1=PARM1
C EVAL VCD2=%TRIM(%SUBST(VCD1:NOFF:4))
C VCD2 DSPLY
C ADD 5 NOFF
C EVAL VCD2=*BLANKS
C EVAL VCD2=%SUBST(VCD1:NOFF:10)
C VCD2 DSPLY
C* 5STUDENT5
C EVAL *INLR=*ON
C RETURN
C*

94
RPG-ILE LABS

LAB : Working with Procedures in the ILE program. Compilation procedure. Variable
life time and scoping. Local and Global variables.

Using procedure in the same application :

Create the Following program : P1 TYPE : RPGLE.

* ---------------------------
*
* ---------------------------
DADDNUM pr 5i 0
dA1 5i 0
dA2 5i 0
DA s 5i 0
DB s 5i 0
DX s 5i 0
c eval A=5
c eval B=20
c eval x=ADDNUM(A:B)
c X dsply
c seton LR
C* ____________________________________________
C*
PADDNUM B
DADDNUM PI 5I 0
DNUM1 5I 0
DNUM2 5I 0
DRES S 5I 0
C EVAL RES=NUM1+NUM2
C RETURN RES
PADDNUM E

Use option 15 to create a Module object. Then use command CRTPGM to create program
object. For CRTPGM, specify the module as P1 and program object name as any name like
, say, P1. this creates a P1 object in the current library.

95
RPG-ILE LABS

LAB : PASS ARGUMENTS BY VALUE / PASS BY REFERENCE

MODULE R0 CALLS PROCEDURES IN MODULES R1 (ILLUSTRATES CALL BY REF AND CALL BY VALUE )

DFN1 PR
DX1 5I 0
DFN2 PR
DX2 5I 0 VALUE
DNUM1 S 5I 0 INZ(10)
DNUM2 S 5I 0 INZ(10)
C NUM1 DSPLY
C CALLP FN1(NUM1)
C NUM1 DSPLY
C NUM2 DSPLY
C CALLP FN2(NUM2)
C NUM2 DSPLY
C SETON LR

MODULE R1 DEFINES MODULES :

HNOMAIN
DFN1 PR
DA 5I 0
DFN2 PR
DB 5I 0 VALUE

PFN1 B EXPORT
DFN1 PI
DA 5I 0
C IF A = 10
C EVAL A = A + 1
C ENDIF
PFN1 E

PFN2 B EXPORT
DFN2 PI
DB 5I 0 VALUE
C IF B = 10
C EVAL B = B + 1
C ENDIF
PFN2 E

96
RPG-ILE LABS

LAB : CALL SUBROUTINES FROM PROCEDURES.

R0 CALL 1 PROCEDURE FROM THE R1 MODULE :


LISTING OF R0 :

DFN1 PR
DX1 5I 0
DNUM1 S 5I 0 INZ(10)
DNUM2 S 5I 0 INZ(10)
C NUM1 DSPLY
C CALLP FN1(NUM1)
C NUM1 DSPLY
C SETON LR

R1 DEFINES THE PROCEDURES (ONE IS EXPORTED)


LISTING OF R1 :

HNOMAIN
DFN1 PR
DA 5I 0
DFN2 PR
DB 5I 0 VALUE
PFN1 B EXPORT
DFN1 PI
DA 5I 0
D*
C IF A=10
C CALLP FN2(A)
C ENDIF
C EXSR SR1
C*
C SR1 BEGSR
C EVAL A=A+5
C ENDSR
PFN1 E
PFN2 B
DFN2 PI
DB 5I 0 VALUE
C IF B = 10
C EVAL B = B + 1
C ENDIF
PFN2 E

LAB : Calling CL (CLLE) Modules from the RPGLE program.

Rpgle Source program that call the CLLE procedure :

* ----------------------------------
| CALLING BOUND CLLE PROCEDURE |
* ----------------------------------
DPROC1 PR
C CALLB 'PROC1'
C SETON LR

CLLE Program called by the above RPGLE program :

97
RPG-ILE LABS

0001.00 pgm
0002.00 WRKSPLF
0003.00 endpgm

LAB : CALLB

R0 : CLIENT APPLICATION :

DFN1 PR
DX1 5I 0
DNUM1 S 5I 0 INZ(10)
C CALLB 'R1' <-- DIRECT CALL TO R1
C NUM1 DSPLY
C CALLP FN1(NUM1)
C NUM1 DSPLY
C SETON LR

R1 MODULE HAS MAIN CODE : NOMAIN IS REMOVED.

DFN1 PR
DA 5I 0
DVAL1 S 5I 0 INZ(10)
C CALLP FN1(VAL1)
C 'MAINCODE END'DSPLY
C SETON LR
C*__________________________________________
PFN1 B EXPORT
DFN1 PI
DA 5I 0
D*
C IF A=10
C EVAL A=A+10
C ENDIF
PFN1 E

98
RPG-ILE LABS

LAB : *VARSIZE

RPCLIENT : Main line code :

DFn1 PR
DStr1 4a OPTIONS(*VARSIZE)
dS1 s 3a inz('abc')
dS2 s 8a inz('abcxyzmn')
dS3 s 1a inz('a')
c
c
C Callp Fn1(s1)
C Callp Fn1(s2)
C Callp Fn1(s3)
C Eval *inlr = *on
C Return

RPAVG : NOMAIN Module used by RPCLIENT

H NOMAIN
dMyds sds
dLnNum 21 28
dStatus *status
d*
dFn1 PR
dstr 4a OPTIONS(*VARSIZE)
PFn1 B Export
dFn1 PI
dstr1 4a OPTIONS(*VARSIZE)
dRslt s 20a
c
c Eval Rslt = 'I Got : '+ str1
c rslt Dsply
PFn1 E

99
RPG-ILE LABS

LAB : Creating Service programs. Accesing methods from client programs.bind by


REFERENCE.

CRTSRVPGM : SPECIFY NAME AS S1.

MODULE : R1

CRTPGM : PROGRAM NAME : P2

MODULE : R0

SERVICE PROGRAM NAME : S1

CALL P2 TO TEST P2.

LAB : Binder Directory.

CRTBNDDIR : Create the B1 object.


WRKBNDDIR : To Add entries select option 9.

LAB : Importing and Exporting Procedures and Variables.

R0 EXPORTS A VARIABLE TO BE ACCESSED AND CHANGED BY ANOTHER MODULE R1.

LISTING OF RO :

DFN1 PR
DX1 5I 0
DNUM1 S 5I 0 INZ(10)
DNUM2 S 5I 0 INZ(25) EXPORT
C NUM2 DSPLY
C CALLB 'R1'
C NUM2 DSPLY
C NUM1 DSPLY
C CALLP FN1(NUM1)
C NUM1 DSPLY
C SETON LR

R1 MODULE :

H*
DNUM2 S 5I 0 IMPORT
DFN1 PR
DA 5I 0
DVAL1 S 5I 0 INZ(10)
C CALLP FN1(VAL1)
C EVAL NUM2=NUM2+100
C NUM2 DSPLY
C 'MAINCODE END'DSPLY
C SETON LR
C*
C* -----------------------------------------
PFN1 B EXPORT
DFN1 PI
DA 5I 0
D*

100
RPG-ILE LABS

C IF A=10
C EVAL A=A+10
C ENDIF
PFN1 E

OUTPUT :

DSPLY 25
DSPLY 125
DSPLY MAINCODE END
DSPLY 125
DSPLY 10
DSPLY 20

Additions to ILE LABS :

LAB : *NOPASS : optional parameter. Need not be passed. Will be passed only if the
need is there.

dP1 PR 2s 0
d 5i 0
d 5i 0
d 10a
d 10a options(*NOPASS)
d*
dn1 s 5i 0 inz(100)
dn2 s 5i 0 inz(8)
ds1 s 10a inz('C')
ds2 s 10a inz('ACAD')
dRetVal s 2s 0 inz(0)
C Eval RetVal=P1(N1:N2:S1)
C Eval *INLR = *ON
C Return
C*--------------------------------------------------
PP1 B
dP1 PI 2s 0
dn1 5i 0
dn2 5i 0
ds1 10a
ds2 10a Options(*NOPASS) // parameter with NOPASS
should

// be at the last.
dlocal s 2s 0
dParams s 5i 0
c 'Procedure' Dsply
c Eval params = %PARMS()
c If params = 4
c 'all 4 passed'dsply
c EndIf
c If params = 3
c '3 passed' dsply
c EndIf
c Eval Local=18
c return Local
PP1 E

101
RPG-ILE LABS

OUTPUT :

DSPLY Procedure
DSPLY 3 passed

NOPASS should be at the end : last parameters should be no pass. Intermediate


parameters cannot be NOPASS. ( Compare this with C++ : Argumentative polymorphism)

Because parameters are positional, once you specify *NOPASS on a parameter, all parameters after
that must be also be coded with *NOPASS. When the procedure is called, if an optional parameter
is omitted, all parameters after that must also be omitted. A procedure can check if an optional
parameter was passed by using the %PARMS built in function. %PARMS will be set to the number
of parameters passed.

Lab : *OMIT

dP1 PR 2s 0
d 5i 0
d 5i 0
d 10a
d 10a options(*OMIT)
d*
dn1 s 5i 0 inz(100)
dn2 s 5i 0 inz(8)
ds1 s 10a inz('C')
ds2 s 10a inz('ACAD')
dRetVal s 2s 0 inz(0)
C Eval RetVal=P1(N1:N2:S1:*omit)
C Eval *INLR = *ON
C Return
C*--------------------------------------------------
PP1 B
dP1 PI 2s 0
dn1 5i 0
dn2 5i 0
ds1 10a
ds2 10a Options(*OMIT)
dlocal s 2s 0
c 'Procedure' Dsply
c Eval Local=18
c return Local
PP1 E

LAB : *OMIT to avoid passing some intermediate parameters.

dP1 PR 2s 0
d 5i 0
d 5i 0
d 10a
options(*OMIT) // this parameters may
not be

102
RPG-ILE LABS

// sent in some cases


d 10a
d*
dn1 s 5i 0 inz(100)
dn2 s 5i 0 inz(8)
ds1 s 10a inz('C')
ds2 s 10a inz('ACAD')
dRetVal s 2s 0 inz(0)
C Eval RetVal=P1(N1:N2:*OMIT:S2)
C Eval *INLR = *ON
C Return
C*--------------------------------------------------
PP1 B
dP1 PI 2s 0
dn1 5i 0
dn2 5i 0
ds1 10a Options(*OMIT)
ds2 10a
dlocal s 2s 0
dParams s 5i 0
c 'Procedure' Dsply
c Eval params = %PARMS() // even when a parameters is not sent,%PARM

// still returns 4
c If params = 4
c 'all 4 passed'dsply
c EndIf
c If params = 3
c '3 passed' dsply
c EndIf
c*
c* S1 is not passed by the calling procedure,so S1's address
c* will be *NULL
c*
c If %addr(S1) = *null
c 'S1 omitted' dsply
c EndIf
c Eval Local=18
c return Local
PP1 E

OUTPUT :
DSPLY Procedure
DSPLY all 4 passed
DSPLY S1 omitted

LAB : Major advantage of Binder Language.

We've seen up to this point that by using bind-by-reference rather than bind-by-copy we have a
much simpler maintenance task. When simple changes are made to the procedures (for example,

103
RPG-ILE LABS

to fix bugs), only the service program needs to be updated. The programs that are bound to the
service program will automatically use the new procedure the next time they are called.

The problem is when we make a less superficial change to a module. If, for example, we add a
new procedure to a module, or add optional parameters to an existing procedure, a different
signature will get generated when we create the service program. All programs that are bound to
that service program will need to be rebound, or they will get a signature violation error when
called.

At first, this seems like a pretty major oversight. The reason signature checks were added to ILE
was to prevent a program from calling a module with unknown changes, possible causing serious
application errors. This is very similar in concept to level checks on database files.

Also like level checks, there is a way around the problem. By using binder language you can
explicitly assign a signature to a service program which will override the system generated one.

LAB : Signature
Signatures

When a service program is created, it is assigned a unique signature based on the procedure
sequence and exports. When a program is bound to a service program, it is bound to the signature
as well. If new procedures are added to the service program, or exports are re-arranged, a
different signature will be generated. If the program is run against the new version of the service
program without being re-bound, a run-time error will generate.

A signature in this sense is very similar to a record format level identifier. If a record format
changes and the program is not re-compiled, you will get a level check error which is very similar
to a signature violation.

By using a binder language you can explicity specify a signature and eliminate signature
violations.

Lets assume we have a source member called PROC1 that has three procedures in it - DayOfWeek,
Uppercase, and Lowercase. In our example, this source member will get compiled into a module,
and a service program will get created from the module.

The binder source for the service program will look like this:

STRPGMEXP PGMVAL(*CURRENT) SIGNATURE('PROC1a')


EXPORT SYMBOL('DayOfWeek')
EXPORT SYMBOL('Uppercase')
EXPORT SYMBOL('Lowercase')
ENDPGMEXP

104
RPG-ILE LABS

When we create the service program with the following command:

CRTSRVPGM SRVPGM(library/PROC1) MODULE(PROC1)


EXPORT(*SRCFILE) SRCFILE(library/sourcefile)
SRCMBR(binder-source)

The service program will then be given a signature of "PROC1a" rather than a system generated
one. If we make changes to the PROC1 module, we can determine ourselves if all programs using
it need to be changed.

If we made simple changes, added procedures, or added optional parms to the end of a procedure
interface, we could retain the existing signature.

If we made changes that we know will require modifications to the calling procedures, we can
assign a new signature of "PROC1b". This will force us to change and re-bind our programs.

LAB : RTVSRVSRC : auto generate the binder language code for a given service program

Create a service program from modules M1, M2, M3. Each modules exports 2 sub-
procedures, thus 6 procedures are exported. Some of these can be suppresed. Instead
of writing the binder language member from sctracth, use RTVSRVSRC and provide name
of the service program to it. The command prepares a member (of NO specific type) and
writes export definations to it. Change type of this member to BND. Comment out all
exports that you do not want to export and then re-create service prgoram using
CRTSRVPGM.

LAB : Type casting

dP1 PR 2s 0
d 5i 0
d 4a
d*
dn1 s 5i 0 inz(100)
d*s1 (cannot pass smaller size) 4a inz('C')
ds1 s 6a inz('ABCDEF')
dRetVal s 2s 0 inz(0)
C Eval RetVal=P1(N1:S1)
C Eval *INLR = *ON
C Return
C*-------------------------------------------------
PP1 B
dP1 PI 2s 0
dn1 5i 0
ds1 4a
dlocal s 2s 0
c s1 Dsply
c Eval Local=18
c return Local
PP1 E

105
RPG-ILE LABS

Although the procedure expects an argument of size 4a, we pass 6a. (less will cause
compiler error). Truncation will happen. Data is stored left justified.

Several important points about procedure parameter typecasting:

1. Automatic conversion will only occur if the expected parameter and the passes parameter
are the same general type. For example, numeric data will not be converted to character.

2. Shorter than expected numeric fields can safely be passed to a procedure. Longer than
expected numeric fields can also passed, however if a significant digit is truncated, you will
get a run-time overflow error.

3. Character strings of a greater length than expected may be passed. Right-side truncation
will occur (similar to MOVEL).

4. The keyword OPTIONS(*VARSIZE) may be coded on the D-specs of the procedure interface
and prototype to allow shorter length than expected character strings.

LAB : Operational Descriptor keyword and the CEEDOD API (should be called to retrieve the length
of the passed field which is controlled by *VARSIZE)

Objective : To get length of data in the field passed as a VARSIZE parameter.

LAB :

LAB :

LAB : supress the main procedure of a module in a service program using a binder
language code,.

106
RPG-ILE LABS

107
RPG-ILE LABS

LAB : Binder Language and UPDSRVPGM.

CLIENT APPLICATION CODE : LECLI1 IN LESRC SOURCE FILE.

* CALLING A PROCEDURE FROM SERVICE PROGRAM LESER2


*
dADDNUM pr 5i 0
dA1 5i 0
dSUBNUM pr 5i 0
dA1 5i 0
D* __________________________________
Da s 5i 0
Db s 5i 0
Dx s 5i 0
c eval a=5
c eval b=20
c eval x=a+ADDNUM(B)
c X dsply
C* ------- ASKING FOR SOMETHING ILLEGAL...
C EVAL X=A+SUBNUM(B)
C X DSPLY
c seton lr

SERVER APPLICATION CODE : WE SHALL EXPORT ONLY THE ADNUM AND SUBNUM FUNCTIONS OUT OF
THE TOTAL 4 FUNCTIONS DEFINED IN THE LESER1 MODULE. (IN THE LESRC SOURCE PF)

HNOMAIN
H* ____________PROTOTYPE SECTION ____________
H* __________________________________________
DADDNUM pr 5i 0
DA1 5i 0
DSUBNUM pr 5i 0
DA2 5i 0
DMULNUM pr 5i 0
DA2 5i 0
DDIVNUM pr 5i 0
DA2 5i 0
D* __________ PROTOTYPE SECTION ENDS __________
D* --------------------------------------------
D*
PADDNUM B export
DADDNUM PI 5i 0
DA1 5i 0
Dresult S 5i 0
C eval result=A1+1
C 'ADDING**' DSPLY
C return result
PADDNUM e
P* __________________________________________
PSUBNUM B export
DSUBNUM PI 5i 0
DA2 5i 0
Dresult S 5i 0
C eval result=A2-1
C 'SUBTRACT*' DSPLY
C return result
PSUBNUM e

108
RPG-ILE LABS

P* __________________________________________
PMULNUM B export
DMULNUM PI 5i 0
DA2 5i 0
Dresult S 5i 0
C eval result=A2*2
C return result
PMULNUM e
P* __________________________________________
PDIVNUM B export
DDIVNUM PI 5i 0
DA2 5i 0
Dresult S 5i 0
C eval result=A2/2
C return result
PDIVNUM e

THE BINDER LANGUAGE MEMBER NAME : S1 TYPE : BND

STRPGMEXP PGMLVL(*CURRENT)
export SYMBOL(ADDNUM)
export SYMBOL(SUBNUM)
endpgmexp

PROCEDURE :

1. Create the client application (LECLI1) that calls the procedures ADDNUM and
SUBNUM. The prototypes of the procedures are given in the client application.
Use option 15 to create the Module oBject of the client application.
2. Create the LESER1 server application as specified in the above code. It
contains 4 procedures, but we wish to export only the 2 procedures : ADDNUM
and SUBNUM.
3. Now create a Binder Language member s1 of the type BND and specify the above
code in it. IT is clear that ADDNUM and SUBNUM are the only procedures
exported.
4. Use CRTSRVPGM to create a service program. Specify the name of the Service
program as S1, Export as *SRCFILE, Export source file as LESRC (all our
program members are in LESRC) and export source member as S1. Since the Binder
language code S1 is guiding th process of creation of the service program,
onlu the exported procedures are now available to client applications.
5. Finally, use CRTPGM to specify LECLI1 as the module (PEP) and S1 as the
service program. The program P1 is created and can be run using CALL P1.
6. Make a change in the LECLI module : Write SOME code that uses MULNUM function.
(SOMETHING LIKE EVAL X = mulnum(B) or so…) After writing the code, convert
the LECLI1 code to Module object by using option 15. The module creates OK
with 00 severity.
7. Now try creating a program P2 using the LECLI1 Module and S1 service program
(as we did while creating P1). The program is not created. This is because the
Binder language code in the S1 (BND) object does not allow export of MULNUM
procedure. Thus we need to make a change in the S1 Member.
8. Change the S1 Binder language member as follows :

STRPGMEXP PGMLVL(*CURRENT)
export SYMBOL(ADDNUM)
export SYMBOL(SUBNUM)
export SYMBOL(MULNUM)
endpgmexp

109
RPG-ILE LABS

9. Use Update Service program (UPDSRVPGM) to update this service program with
the new Binder language definition (in addition, you also need to specify the
LESER1 module object in the parameters of this command).
10. Use CRTPGM to create a program object P2 from LECLI1 And S1 service program.

110
RPG-ILE LABS

LAB : Using CALLB to call main line code in a Module. Exchange data using IMPORT And
EXPORT.

Calling Application Code : LEMNCLI TYPE : RPGLE

* ________________________________________________________
* THIS MODULE CALLS THE LEMN MODULE WITH A CALLB OPCODE.
* N1 AND N2 ARE EXPORTED WHILE LEMN EXPORTS THE AVGNUM VARIABLE
* WHICH CONTAINS THE AVERAGE CACULATED BY LEMN.
* ________________________________________________________
*
*
DN1 s 5i 0 EXPORT
DN2 s 5i 0 EXPORT
DAVNUM s 5i 0 IMPORT
C eval N1=10
C eval N2=10
C CALLB 'LEMN'
C AVNUM DSPLY
C SETON LR

Called Application Code : LEMN TYPE : RPGLE


( Note : Module name should be in CAPS. )

* ________________________________________________________
* THIS MODULE HAS MAIN LINE CODE THAT WILL BE CALLED
* BY CLIENT APPLICATION USING CALLB OPCODE.
* N1 N2 VALUES COME FROM THE CLIENT APPLICATION
* WHILE THE COMPUTED VALUE OF AVNUM (AVERAGE) IS EXPORTED
* BY THIS MODULE.
* ________________________________________________________
*
*
DN1 s 5i 0 IMPORT
DN2 s 5i 0 IMPORT
DAVNUM s 5i 0 EXPORT
C eval AVNUM=((N1+N2)/2)
C SETON LR

Creation : Use option 15 for both to create their respective module objects and then
use CRTPGM to create a program out of those modules.

* * *

111
RPG-ILE LABS

COMPARISON CHART

RPG/400 RPG ILE

OPM Model ILE Model


All variables global Global as well as local
Subroutines for modularity Subroutines, procedures and modules
give very high degree of modularity
and ease of of software Testing
Only 1 H specs Many
50 F specs Many
FC for giving additional details Keywords instead of FC
HFELICO HFDICOP
Dynamic calls Dynamic and Static calls
OPM debugger ILE debugger
Opcodes are 5 characters 10 characters max
Data types : S,P,A,L etc D –specs
C-specs for calculation CX : extended C specs : EVAL
New opcodes : IF, DOW, SELECT, CALLB
No built-in functions Large number of Built-in functions
Not ideal for huge projects and Very mature : ease of coding. Code re-
serious dead lines use, modularity and ease of testing
making development fasters
Poor readability Improved readability
Programs run in def act grp Can run in dft act grp (provided ILE
extensions are not used) in a
compatilbity mode. Can be run in
separate activation groups
(recommended)
ODP shared by programs tend to have OPD shared by programs need not share
problems with recordf pointer position same fil epointer if programs run in
separate activation groups.
3 indicators to condition C-spec line Only 1 indicator. Multiple indicators
converted to multiple lines.
Scaterred : declarations in I,C and E Structured and planned : All
specs declarations go in D specs
Indicators to know result of Indicatorless programming : Functions
operations tell status.

112
RPG-ILE LABS

OPERATION EXTENDERS :

RPG/400
READ BM N
55

N is to read a record without locking the same

ILE – RPG :
READ(N) BM
5

(H) : Half Adjust


Result of calculation to be ROUNDED.(exceptions are DIV,MVR)

(P) : Pad the resulting string on the RIGHT hand side rather than left hand side.

Suppose S1 = “ABC” (size of this var is 3)


Suppose S2 = “bbbbbbbb” ( 8 spaces )

MOVE S1 S2
Causes a padding of S2 on left.

S2 = “bbbbbABC”

MOVE(P) S1 S2

Causes a padding of S2 on the Right.


Padding is done for MOVEA,MOVEL,SUBST,XLATE

113
RPG-ILE LABS

CHEAT SHEET

THE LIMITS CHEAT SHEET

MAX RECORDS IN PF : 10,000 + 3000

MAX FIELDS IN PF : 7000

MAX KEYED FIELDS IN PF : 8

MAX LF BASED ON PF : 32

MAX DECIMAL POSITIONS FOR ZONED / PACKED : 30

MAX LENGTH OF CHARACTER FIELD : 32,767

MAX VALUES FOR SPACEA AND SPACEB : 255

FIELD / ARRAY NAME = DS NAME = FILE NAM = REC FMT NAME = 10


CONSTANT SIZE = 1024
DS SIZE = 32767
NO OF ARRAY ELEMENTS = 32767
NAMED CONSTANT = 1024
SEE PAGE 38 OF MOVING TO ILE

114
RPG-ILE LABS

MORE ON SPECIFICATIONS

F specs : PROGRAM DECSRIBED FILES


FX SPECS : EXTERNALLY DESCRIBED FILES.
E SPECS : EXTENSION SPECS : ELIMITED IN RPG ILE
L SPECS : LINE COUNTER SPECS : ELIMITED IN RPG ILE

Notes and TESTED programs :

The Integrated Language Environment introduced with OS/400 Version 2 Release


3 and the new RPG IV language definition in Version 3 Release 1 writes the next
chapter on RPG and AS/400 programming.

The RPG IV language:


1. Re-formats and simplifies the RPG specifications forms and at the same time.
2. Adds new functions, most of them to answer customer requests.
3. Removes some of the column-orientation limitations and introduces the
4. capability of free-format arithmetic expressions and built-in functions.
5. Lifts the RPG file, field and array name length restrictions.
6. Expands and removes some of the language limitations, such as the number
7. of files, and the number and size of arrays.
8. Allows usage of uppercase and lowercase in symbolic names.
9. Offers better support for date and time operations.
10. Adds new functions and improves some of the existing functions.
11. Prepares the languages for future enhancements and growth.
12. Allows participation in the new Integrated Language Environment (ILE).

115
RPG-ILE LABS

CONVERSION CONSIDERATIONS

CVTRPGSRC

Source: details of the Source RPG file, member type, Soruce PF and library
Target : Name of LE source physical file,Member name and library name.
EXPAND COPY MEMBER EXPCPY: SET THIS TO *YES If you are using a /COPY in the source
member.

FREE and DEBUG operations in RPG /400 are not supported in RPG LE.

H-SPEC KEYWORDS

ALTSEQ Alternate collating sequence


CURSYM Currency symbol
DATEDIT Date edit code
DATFMT Date format
DEBUG Debug option
DECEDIT Decimal notation
DFTNAME 80 Program or module identification
FORMSALIGN Forms alignment
FTRANS File translation

116
RPG-ILE LABS

Lab : Select a record format from a LF (amongst the multiple record formats)

Create 2 physical files : BMAST and PMAST (book master and publisher master)
Create a LF as follows :

A R BM PFILE(BKMAST)
A BCODE
A BNAME
A BPRICE
A K *NONE
A R PM PFILE(PMAST)
A PCODE
A PNAME
A K *NONE

The LF combines all fields in the 2 physical files as shown above.

RUNQRY on the LF returns records only from the first record format.
From ILE (or RPG) you can specify which record format is to be accessed as follows :

FJOINLF IF E DISK INCLUDE(BM)


C READ JOINLF 44
C BCODE DSPLY
C BNAME DSPLY
C BPRICE DSPLY
C PCODE DSPLY
C SETON LR

RPG/400 EQUIVALENT
------------------

FFILE1 UF E
DISK
F FMT1
KIGNORE
F FMT2
KIGNORE
F FMT3
KCOMMIT

This renaming of input database fields is not required in RPG IV since the limits
have been increased.

117
RPG-ILE LABS

NEW / ENHANCED KEYWORDS


KEYWORD{(VALUE)} RPG/400 DESCRIPTION
COMMIT{(RPG-NAME)} COMIT option in FC spec Commitment control
DATFMT(format{seperator}) N/a
FORMLEN(number) Pos 18-19 on L-specs Form length of PRINTER
file
FORMOFL(number) Pos 20-22 on L specs Line number specified in
overflow line
OFLIND(indicator) Pos 33-34 Overflow indicator
PLIST(Plist parameters) PLIST option on Parm list to be passed
continuation line to program given in
PGMLIST keyword
RECNO(fieldname) RECNO option on cont DISK file processed by
line RRN
RENAME(ExtFmtNam:IntFmtNa RENAME option on cont To rename rec fmt of
m) line externally desc files.
SFILE(rcdFmtNam:RRN) SFILE option on cont First param is SFLDT sec
is RRN variable
TIMFMT(format{seperator}) N/a Default time format and
optional time seperator
USROPN UC on pos 71-72 User controlled open of
file

118
RPG-ILE LABS

Chapter 3 : RPG FUNCTIONS AND FEATURES


(MOVING TO ILE)

FOCUS : FUNCTIONAL ENHANCEMENTS.

LAB : Study of RENAMED opcodes


Some of them are RETURN, OCCUR,SETOFF,UNLOCK,WHENxx

LAB : RENAMING a record format name

FpfBMAST iF E DISK rename(bm:newbm)


C Read newBM 88
C bcode Dsply
C Eval *inlr =*on
C Return

119
RPG-ILE LABS

CHAPTER 3 : ILE ADVANCED CONCEPTS

LAB : Working with Date validation.

Program to accept date as a simple number and test of it is valid or not.


Program writes in Date value to a date variable only if the value is Valid.

This is the best way of entering dates from the user.

BEST PRACTICE : Input the date from the user as a sinple 6S 0 numeric value. Proper
edit code and edit word should be used. Test this number (for example : 311204 using
the TEST(D) opcode. Specify the proper Format (such as *DMY) in the factor 1 and
check the state f the indicator in the LO section. Of the Indicator remains off, the
date is correct. This,way, the onus of checking correctness of the date (including
leap years and other factors) is on the system.

Even the PSSR or ERRMSG is not required.

Display file listing :

DSDATE2 :

A DSPSIZ(24 80 *DS3)
A CA03(03)
A R RDATE
A 5 10'INPUT THE DATE YOU WISH TO TEST’
A 8 10'===> '
A COLOR(BLU)
A FLD001 6Y 0B 8 17EDTWRD(' / / ')
A EDTMSK(' & & ')
A 6 10'(Format : DD/MM/YY'
A 6 29')'
A 12 11'Press ENTER to check...'
A COLOR(BLU)

INPUT THE DATE YOU WISH TO


TEST
(Format : DD/MM/YY )

===> ________

Press ENTER to check...

RPGLE program : RPDATE2 :

H DATFMT(*DMY)
FDsdate2 CF E WORKSTN
DDT1 S D
D* fld001 IS A 6S 0 FIELD : SIMPLE NUMERIC FIELD BUT HAS APPEARANCE

120
RPG-ILE LABS

D* OF DATE FIELD DUE TO EDIT WORD AND EDIT MASK.


D* __________________________________________________________________
D*
C DOW *IN03 = *OFF
C MOVE *ZEROS fld001
C EXFMT RDATE
C *DMY TEST(D) fld001 77
C IF *IN77 = *ON
C EVAL *IN77 = *OFF
C 'INVALID' DSPLY
C ELSE
C *DMY MOVE fld001 DT1
C DT1 DSPLY
C ENDIF
C ENDDO
C SETON LR

Lab : sample Data entry and validation program.

Display file : DSDATAENT

A*%%TS SD 20040704 073607 SAM2 REL-V3R7M0 5716-PW1


A*%%EC
A DSPSIZ(24 80 *DS3)
A CF10(10)
A CA12(12)
A CF07(07)
A R RDATAENT
A*%%TS SD 20040704 073607 SAM2 REL-V3R7M0 5716-PW1
A 1 8'BOOK MASTER DATA ENTRY'
A 5 2'SPECIFY THE DATA AND PRESS F10 TO -
A SAVE'
A COLOR(BLU)
A 8 3'CODE : '
A COLOR(WHT)
A 10 3'NAME : '
A COLOR(WHT)
A 12 3'PRICE : '
A COLOR(WHT)
A DCODE 4S 0B 8 12COLOR(WHT)
A 90 DSPATR(RI)
A DNAME 10A B 10 12COLOR(WHT)
A 91 DSPATR(RI)
A DPRICE 7Y 2B 12 12EDTWRD(' . ')
A 92 DSPATR(RI)
A COLOR(WHT)
A 17 4'__________________________________-
A _______ '
A COLOR(BLU)
A 18 5'F10:SAVE F12:CANCEL F7:VALID-
A ATE'
A COLOR(BLU)

Module for validation : MVLD000001

HNOMAIN
FPFBM5 UF A E DISK
F*
D* --- VALIDATION ---
D*

121
RPG-ILE LABS

DVLD_DT PR 4S 0
DDCODE 4S 0 VALUE
DI1 1A
DDNAME 10A VALUE
DI2 1A
DDPRICE 7S 2 VALUE
DI3 1A
D* --- SAVE DATA TO PFBM5 ---
D*
DSAVE_DATA PR 4S 0
DDCODE 4S 0 VALUE
DDNAME 10A VALUE
DDPRICE 7S 2 VALUE
P*1
PSAVE_DATA B EXPORT
DSAVE_DATA PI 4S 0
DDCODE 4S 0 VALUE
DDNAME 10A VALUE
DDPRICE 7S 2 VALUE
DRETVAL S 4S 0 INZ(1)
C* DOES ALL SAVING TO PHYSICAL FILE
C*
C READ BM 44
C EVAL BCODE=DCODE
C EVAL BNAME=DNAME
C EVAL BPRICE=DPRICE
C WRITE BM 77
C* CHECK WRITE ERROR
C IF *IN77=*ON
C EVAL RETVAL=0
C* WRITE WAS NOT SUCCESSFUL
C*
C ELSE
C EVAL RETVAL=1
C* WRITE WAS SUCCESSFUL
C ENDIF
C RETURN RETVAL
PSAVE_DATA E
PVLD_DT B EXPORT
DVLD_DT PI 4S 0
DDCODE 4S 0 VALUE
DI1 1A
DDNAME 10A VALUE
DI2 1A
DDPRICE 7S 2 VALUE
DI3 1A
DRETVAL S 4S 0 INZ(1)
C*
C* START VALIDATION FOR DCODE
C*
C IF ((DCODE<100) OR (DCODE > 700))
C EVAL I1 = '1'
C ELSE
C EVAL I1 = '0'
C ENDIF
C*-
C*
C* START VALIDATION FOR DNAME
C*
C IF DNAME=*BLANKS

122
RPG-ILE LABS

C EVAL I2 = '1'
C ELSE
C EVAL I2 = '0'
C ENDIF
C*
C* START VALIDATION FOR DPRICE
C*
C IF DPRICE<0
C EVAL I3 = '1'
C ELSE
C EVAL I3 = '0'
C ENDIF
C*
C* ATLEAST 1 INDICATOR IS ON IF DATA IS NOT VALID
C* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C IF ((I1 = '1') OR (I2 = '1') OR (I3 = '1'))
C EVAL RETVAL=0
C ELSE
C EVAL RETVAL=1
C ENDIF
C*
C RETURN RETVAL
C*
PVLD_DT E
P* ------------------------------------------

The Entry point module : RPDATAENT


Displays the display file for user to input data.

FDSDATAENT CF E WORKSTN DATA


ENTRY FILE
F*
D* -----------------------------------------
DRETVAL S 4S 0 INZ(1)
DRETARR S 4S 0 DIM(20)
D*
D* ------------------------------------------
D* RETVAL,RETARR CONTAINS GENERAL ERROR CODE
D* AND VARIABLE SPECIFIC ERROR CODE
D* -----------------------------------------
D* PROCEDURE PROTOTYPES BEGIN
DVALIDATE_DATA PR 4S 0
DDCODE 4S 0 VALUE
DDNAME 10A VALUE
DDPRICE 7S 2 VALUE
DVLD_DT PR 4S 0
DDCODE 4S 0 VALUE
DI1 1A
DDNAME 10A VALUE
DI2 1A
DDPRICE 7S 2 VALUE
DI3 1A
DSAVE_DATA PR 4S 0
DDCODE 4S 0 VALUE
DDNAME 10A VALUE
DDPRICE 7S 2 VALUE
D* PROCEDURE PROTOTYPES END
C DOW *IN12 = *OFF MAIN
C EXFMT RDATAENT

123
RPG-ILE LABS

C*-(
C IF *IN12 = *ON MAIN
C EVAL *INLR = *ON
C RETURN
C ENDIF
C IF *IN07=*ON
C EVAL *IN90 = *OFF
C EVAL *IN91 = *OFF
C EVAL *IN92 = *OFF
C EVAL RETVAL=VLD_DT(DCODE:*IN90:DNAME:*IN91:DPRICE
C :*IN92)
C IF RETVAL = 1
C EVAL RETVAL = SAVE_DATA(DCODE:DNAME:DPRICE)
C ENDIF
C ENDIF
C ENDDO

124
RPG-ILE LABS

LAB : First program for Pointer operation

DN1 S 4S 0 inz(120)
DS1 S 4A
DPtr1 S *
C EVAL Ptr1 = %ADDR (N1)
C EVAL S1 = %Str(Ptr1)
C S1 DSPLY
C EVAL *inlr = *on

LAB : Second program on pointers

DS1 S 4A inz('pqrs')
DS2 S 4A
DPtr1 S *
C EVAL Ptr1 = %ADDR (S1)
C EVAL S2 = %Str(Ptr1)
C S2 DSPLY
C*output : pqrs
C EVAL S1 = *BLANKS
C EVAL %Str(Ptr1:5) = 'abcd'
C* In the above expr. abcd is loaded into the pointer
C* from position 1 of abcd to position 4 abcd. Scanning stops at
C* position 5. thus 5 is the number of characters read from the RHS
C* expression.
C* OUTPUT : abcd
C S1 dsply
C EVAL *inlr = *on

LAB : Third program on pointers

Pointer to a Data Structure.


Later, this pointer can be passed as argument to a validation procedure. The
procedure will write results of the validation to the data structure.

DDS1 ds
DS1 30A
DS2 30A
DS3 30A
DPtr1 S *
Dstr S 90A
D*-------------------------------------------
C EVAL Ptr1 = %Addr(DS1)
C eval str = 'CODE not between 100&700 '
C 'Name cannot be BLANK ' +
C 'Price cannot be Negative'
C EVAL %Str(Ptr1:(%Size(str)+1))=str
C S1 DSPLY
c S2 DSPLY
c S3 DSPLY
C EVAL *INLR = *ON

LAB : Pointers

Linkage : RPPOINTER

125
RPG-ILE LABS

CODE :

Ds1 s 5a inz('xyz')
Ds2 s 5a inz(' ')
Dps1 s *
c Eval ps1 = %Addr(s1)
c Eval %Str(ps1:4) = 'abc'
c* _____________________________________________________________
c* |%Str(ps1:4) <- Load 'abc' into positions 1,2,3 of ps1.
c* |4th pos is for the terminator which is added automatically.
c* |____________________________________________________________
c s1 Dsply
c Eval s2 = %Str(ps1)
c s2 Dsply
c Eval *inlr=*on

PF contents :

OUTPUT :

REMARKS :

LAB : Pointer

Linkage : ---

CODE :

Ds1 s 5a inz(' 123')


Dn1 s 5i 0
Ds2 s 5a
Dps1 s *
c Eval ps1 = %Addr(s2)
c Eval %STR(PS1:6) = S1

c* Populate the first 5 positions of the variables to which ps1 points


c* with contents of s2.6th position is for the terminator.

c s2 dsply
c Move s2 n1
c Eval n1 = n1 + 1
c n1 Dsply
c Eval *inlr=*on
C* OUTPUT :
C* 123
C* 124

PF contents :

126
RPG-ILE LABS

OUTPUT :

REMARKS :

LAB : Pointer oepration

Linkage :

CODE :

Linkage : RPPOINTER1

d* Illustrates passing a pointer as a argument to a function.


d* Converting the text contents (actually '123') to numeric
d* doing some processing on the numeric data and re-converting
d* back to string and storing the result to pointer.
d*
dFn1 PR
dp *
d*
Ds2 s 5a inz(' 107')
Dps1 s *
c Eval ps1 = %Addr(s2)
c callp Fn1(Ps1)
c s2 Dsply
c Eval *inlr=*on
c* ----------------------------------------
c*
PFn1 B
DFn1 PI
dpArg1 *
dTemp s 5a
dTempn s 5i 0
c Eval Temp = %Str(pArg1)
c move Temp Tempn
c Eval Tempn = Tempn + 1
c move Tempn Temp
c Temp dsply
c Eval %Str(pArg1:6) = Temp
PFn1 E

PF contents :

OUTPUT :

REMARKS :

127
RPG-ILE LABS

LAB : Return pointer to Data Structure

2 modules implemented as follows : M1 and M2

M1 Listing :

H DATFMT(*DMY)
DDs001 ds
DDys 2a
DMnt 2a
DYrs 2a
DFind_Difference PR
DD1 d
DD2 d
Dpr *
D*---------------------------------------------------
DD1 s D INZ(D'27/01/04')
DD2 S D INz(D'15/03/04')
Dpr s * inz(*NULL)
dTemp s 8a
D*
c EVAL pr = %Addr(Ds001)
C CAllp Find_Difference(D1:D2:pr)
c EVAL Temp = %Str(pr:7)
c Temp dsply
C Eval *inlr = *on
C Return
C* -------------------------------------------------------

M2 Listing :

H* Module TO CALCULATE THE TIME DIFFERENCE BETWEEN 2 date VALUES.


h NOMAIN DATFMT(*DMY)
DFind_Difference PR
DD1 d
DD2 d
Dpr *
D* -------------------------------------------------
PFind_Difference B export
DFind_Difference PI
DD1 d
DD2 d
Dpr *
D*---
DYrs s 2s 0 inz(0)
DMnt s 2s 0 inz(0)
Ddys s 2s 0 inz(0)
DYrs1 s 2a
DMnt1 s 2a
Ddys1 s 2a
Dtemp s 8a
C D2 SUBDUR D1 Yrs:*Y
C D1 addDUR Yrs:*Y D1
C D2 SUBDUR D1 Mnt:*M
C D1 addDUR Mnt:*M D1
C D2 SUBDUR D1 Dys:*D
c movel yrs yrs1
c movel mnt mnt1
c movel dys dys1

128
RPG-ILE LABS

c EVAL temp = dys1+mnt1+yrs1


c EVAL %STR(pr:7) = temp
C Return
PFind_Difference E

Purpose is to calculate days,months and years between 2 dates. The calculation is


done by a procedure in module M2 which is NOMAIN module. It recieves D1,D2 and PR
(pointer to DS defined in M1) Values are assigned to pointer that causes data to load
into the DS defiend in M1.

LAB :

Linkage :

CODE :

Linkage : RPPOINTER2

Listing :
d*
d* __________________________________________________________
d* Simple program to illustrate a pointer to a Data structure.
d* The pointer to DS is passed as a argument to a procedure
d* Processing can be done in the procedure.
d* ___________________________________________________________
d*
dFn1 PR
dp *
dDS001 DS
Ds1 15a inz('This is')
Ds2 15a inz('a test')
D*
Dps1 s *
c Eval ps1 = %Addr(DS001)
c callp Fn1(Ps1)
c Eval *inlr=*on
c* ----------------------------------------
c*
PFn1 B
DFn1 PI
dpArg1 *
dTemp0 s 30a
dTemp1 s 15a
dTemp2 s 15a
c Eval Temp0 = %Str(pArg1)
c Eval Temp1 = %Subst(Temp0:1:15)
c Eval Temp2 = %Subst(Temp0:16:15)
c Temp1 dsply
c Temp2 dsply
PFn1 E

PF contents :

OUTPUT :

129
RPG-ILE LABS

REMARKS :

LAB : Pointer to a DS

Linkage :

CODE :

Pass a pointer to DS to a function that will decipher the data in the DS and display
it in strings of length 10.
Main thing here is that Multi occurances of DS can be any value. The length of s1 (a
component of DS) can be any value.

Only condition :

Occurances * size of Base (s1 ) > = 10

d*
d* __________________________________________________________
d* DS of any size can be passed. Only condition is as follows :
d* (no of occurances * sizeof(s1) ) > 10
d* and should be a multiple of 10.
d* ___________________________________________________________
d* TARGET : In the next program, show this data in a Window Subfile !
dFn1 PR
dp *
d 4s 0
d 4s 0
d*****
dnOccurs s 4s 0 inz(40)
d* // MUST contain no of occurances of the data structure.
dnSize s 4s 0 inz(20)
d* // MUST contain size of S1 which is the only member of the data
d* // structure.

dDS001 DS occurs(40)
Ds1 20a inz('aaa')
D*
Dps1 s *
c Eval ps1 = %Addr(DS001)
c callp Fn1(Ps1:nOccurs:nSize)
c Eval *inlr=*on
c* ________________________________________
PFn1 B
DFn1 PI
dpArg1 *
dnOccurs 4s 0
dnSize 4s 0
d*----------------------------------------
dnLoops s 4s 0
dnStPos s 4s 0
dnCntr s 4s 0 inz(0)
d*-------------------------------------------
dnBase s 4s 0 inz(10)
d* nBase is always 10 !!!
d*-------------------------------------------

130
RPG-ILE LABS

d* var is the variable that will hold 10 positions of data from the input
d* total data.
dvar s 10a
c Eval nLoops = (nOccurs * nSize)/10
c Do nLoops
c Eval nStPos = (nBase * nCntr)+1
c Eval var = %Subst(%Str(pArg1):nStPos:nBase)
c Eval nCntr = nCntr + 1
c var Dsply
c EndDO
c 'loops :' dsply
c nLoops dsply
PFn1 E

PF contents :

OUTPUT :

REMARKS :

Suppose Element s1 in DS001 is of the size 40. The number of occurances of the SD are
20.
Total size = 40 * 20 = 800.
WE wish to break this 800 into units of 10 since the variable that will hold the data
will have a size of 10.
Thus number of iterations for the loop that shows those 800 bytes are 800/10 = 80.
WE access 10 positions at a time of this 800 characters long string by using
substring().

Data type conversion

LAB : Convert string to int

Linkage :

CODE :

Linkage : RPCONV

ds1 s 5a inz('123')
dn1 s 5s 0 inz(108)
c Eval n1 = %Int(s1)
c Eval n1 = n1 + 1
c n1 dsply
c Eval *inlr = *on

PF contents :

OUTPUT :

131
RPG-ILE LABS

REMARKS :

132
RPG-ILE LABS

LAB : Simple Error handling

dMyPsds sds
dSts *status
derr_line_no 21 28
dnsts s 4s 0 inz(0)
dArg1 s 4s 0 inz(12)
dArg2 s 4s 0 inz(0)
dRslt s 4s 0 inz(0)
dRtPoint s 6a
dTemp s 4s 0 inz(0)
c '-------' Dsply
c 'Start..' dsply
c '-------' Dsply
c Opr1 Tag
c Eval Rslt = Arg1 / Arg2
c Rslt Dsply
c '--- ' Dsply
c Eval *inlr = *on
c Return
c*
c*
c *pssr BEGSR
c Move sts nsts
c Move err_line_no Temp
c* is the error divide by zero ? ie 102 ?
c If nsts = 102
c Eval Arg2=2
c else
c* error is not a divide by zero End program.
c Eval RtPoint = '*CANCL'
c Endif
c If RtPoint <> '*CANCL'
c goto Opr1
c Endif
c Endsr RtPoint

OUTPUT :

DSPLY -------
DSPLY Start..
DSPLY -------
DSPLY 6

Program requests a Starting position outside the string length thus causing control
to jump into the PSSR error handler. PSSR displays lot of information.

133
RPG-ILE LABS

FDSERR CF E WORKSTN
DString1 s 10a inz('abcdefghij')
DStPos s 2s 0 inz(3)
DNumOfChar s 2s 0 inz(4)
DRslt s 10a
D*
DMyPSDS sds
DErr_Status *status
DErr_ProcName *Proc
DErr_Routine *Routine
DERr_LineNum 21 28
DErr_ExcpType 40 42
DErr_ExcpNum 43 46
DErr_PgmLib 81 90
DErr_ExcpData 91 170
DErr_ExcpID 171 174
DErr_Date 191 198
DErr_Year 199 200s 0
DErr_User 254 263
DErr_FileInfo 209 243
D*------------------------------------------------------------------
c Eval Rslt = %SubSt(String1:StPos:NumOfChar)
c Rslt Dsply
c* output : cdef
c Eval StPos = 10
c Eval NumofChar = 1
c Eval Rslt = *All' '
c Eval Rslt = %SubSt(String1:StPos:NumOfChar)
c Rslt Dsply
c* output : j
c* -------------------------------------
c* Deliberately cause an error condition
c* give an invalid starting position.
c*
c Eval StPos = 12
c Eval NumofChar = 4
c Eval Rslt = *All' '
c Eval Rslt = %SubSt(String1:StPos:NumOfChar)
c Rslt Dsply
c* output : ?
c 'Prg ENDED' DSPLY
c Eval *inlr = *on
c Return
c*
c* =====================================
c *PSSR BEGSR
c movel Err_excpdata DExcpData
c exfmt Rerr
c 'pssr' DSPLY
c 'Line number' dsply
c Err_Linenum dsply
c 'Err_Status' dsply
c Err_Status dsply
c 'Err_ProcName'dsply
c Err_ProcName dsply
c 'Err_Routine' dsply
c Err_Routine dsply
c 'Err_ExcpType'dsply
c Err_ExcpType dsply
c 'Err_ExcpNum' dsply

134
RPG-ILE LABS

c Err_ExcpNum dsply
c 'Err_PgmLib' dsply
c Err_PgmLib dsply
c* Err_ExcpData dsply
c 'Err_ExcpID' dsply
c Err_ExcpID dsply
c 'Err_Date' dsply
c Err_Date dsply
c 'Err_Year' dsply
c Err_Year dsply
c 'Err_User' dsply
c Err_User dsply
c 'Err_FileInfo'dsply
c Err_FileInfo dsply
c EVAL StPos = 1
c EVAL NumOfChar = 3
c*
c*
c* GETIN causes control to start from the First C-spec line in the
c* Program ! Cannot use GETIN
c* GETIN actually stands for GET INPUT REC which reads next record
c* from next run of the Logic Cycle.
c* DETC also does same thing. Not specifying anything in the Factor 2 of
c* ENDSR also does not solve the problem. The system error handler is
c** displayed after PSSR executes of nothing is specified in Factor 2.
C* solution to this problem can be found in the next lab.
C*
c* ENDSR '*GETIN'
c*
c ENDSR

Output
Error Data was displayed in a Display File :
error data :

Length or start position is out of range for the string operation.

DSPLY cdef
DSPLY j
DSPLY pssr
Err_Status DSPLY 100
Err_ProcName DSPLY RPSCAN
Err_Routine DSPLY *DETC
Err_ExcpType DSPLY RNX
Err_ExcpNum DSPLY 0100
Err_PgmLib DSPLY SAM2
Err_ExcpData DSPLY
Err_ExcpID DSPLY 07062004
Err_Date DSPLY 20
Err_Year DSPLY SAM2
Err_User DSPLY
Err_FileInfo

LAB : Error Handling

*************** Beginning of data *********************************


0001.00 D* Program demonstrates Exception handling.Program has

135
RPG-ILE LABS

0002.00 D* 3 SubSt statements. any of them can have an error.Typical


0003.00 D* error condition is simulated by setting starting position
0004.00 D* for SubSt to an excessively large value. Thus a call
0005.00 D* to SubSt causes control to enter PSSR. The PSDS
0006.00 D* contains a important variable - Err_LineNum (u can change
0007.00 D* the name) that contains the line number of the code
0008.00 D* that caused the error. (this line number is the physical line
0009.00 D* number from the top of the code. Count lines occupied by Comment
0010.00 D* statement also !.
0011.00 D* Thus you can check against line number and cause a GOTO to
0012.00 D* appropriate position.
0013.00 D*
0014.00 D* ----------------------------------------------------------
0015.00 D*
0016.00 DString1 s 10a inz('abcdefghij')
0017.00 DStPos s 2s 0 inz(15)
0018.00 DNumOfChar s 2s 0 inz(4)
0019.00 DRslt s 10a
0020.00 DLineNum s 9s 0 inz(0)
0021.00 DMyPSDS sds
0022.00 DErr_Status *status
0023.00 DERr_LineNum 21 28
0024.00 c OPR1 TAG
0025.00 c* Line number of following eval statement is 26.
0026.00 c Eval Rslt = %SubSt(String1:StPos:NumOfChar)
0027.00 c Rslt Dsply
0028.00 c*
0029.00 c* delibrately cause and error
0030.00 c*
0031.00 c Eval StPos = 44
0032.00 c Eval NumofChar = 4
0033.00 c Eval Rslt = *All' '
0034.00 c OPR2 TAG
0035.00 c* Line number of following eval statement is 36.
0036.00 c Eval Rslt = %SubSt(String1:StPos:NumOfChar)
0037.00 c Rslt Dsply
0038.00 c*
0039.00 c* -------------------------------------
0040.00 c* Deliberately cause an error condition
0041.00 c* give an invalid starting position.
0042.00 c*
0043.00 c Eval StPos = 12
0044.00 c Eval NumofChar = 4
0045.00 c Eval Rslt = *All' '
0046.00 c OPR3 TAG
0047.00 c* Line number of following eval statement is 48.
0048.00 c Eval Rslt = %SubSt(String1:StPos:NumOfChar)
0049.00 c Rslt Dsply
0050.00 c*
0051.00 c 'Prg ENDED' DSPLY
0052.00 c Eval *inlr = *on
0053.00 c Return
0054.00 c*
0055.00 c*
0056.00 c *PSSR BEGSR
0057.00 c 'pssr' DSPLY
0058.00 c 'Line number' dsply
0059.00 c Err_Linenum dsply
0060.00 c 'Err_Status' dsply
0061.00 c Err_Status dsply

136
RPG-ILE LABS

0062.00 c*
0063.00 c* Convert to Numeric
0064.00 c*
0065.00 c Move Err_LineNum LineNum
0078.00 c EVAL StPos = 1
0079.00 c EVAL NumOfChar = 3
0080.00 c If LineNum = 26
0081.00 c Goto OPR1
0082.00 c Endif
0083.00 c If LineNum = 36
0084.00 c Goto OPR2
0085.00 c Endif
0086.00 c If LineNum = 48
0087.00 c Goto OPR3
0088.00 c Endif
0090.00 c ENDSR

Output :

DSPLY pssr
DSPLY Line number
DSPLY 00000026
DSPLY Err_Status
DSPLY 100
DSPLY abc
DSPLY pssr
DSPLY Line number
DSPLY 00000036
DSPLY Err_Status
DSPLY 100
DSPLY abc
DSPLY pssr
DSPLY Line number
DSPLY 00000048
DSPLY Err_Status
DSPLY 100
DSPLY abc

LAB : Work on TESTN

dNumericData s 4a inz('120')
dCharData s 4a inz('abc')
dBlankData s 4a
d*
c TESTN NumericData 777879
c* 78 becomes on since variable contains leading spaces.
c* No indicator will be on if data is numeric and has no leading
c* spaces.
c*
c exsr dspsr
c TESTN CharData 777879
c* no indicator is on since data not numeric
c exsr dspsr
c TESTN BlankData 777879
c* Equal indicator on since data is blank.
c exsr dspsr
c Eval *inlr = *on
c Return

137
RPG-ILE LABS

c*
c dspsr Begsr
c *in77 dsply
c *in78 dsply
c *in79 dsply
c Eval *in77=*Off
c Eval *in78=*Off
c Eval *in79=*Off
c Endsr

138
RPG-ILE LABS

LAB : Handling ESCAPE messages

The RPGLe program calls a CLP program that sends a *PRV Pgm msg that is not displayed
on the screen. Then it sends a PGM MSG of the type *ESCAPE which causes control to
immediately return back into RPGLE (ignoring the WRKSPLF in the CLP) the control
enters PSSR and displays various parameters of the error MSG thus received from the
child application. If the parent application in this case was a CL program, it would
have used program level monmsg .

RPGLE Program :

Fdserr cf e workstn
DMyPSDS sds
DErr_Status *status
DErr_ProcName *Proc
DErr_Routine *Routine
DERr_LineNum 21 28
DErr_ExcpType 40 42
DErr_ExcpNum 43 46
DErr_ExcpData 91 170
DErr_ExcpID 171 174
c 'Before' dsply
c call 'CLERR'
c end1 Tag
c 'After' dsply
c Eval *inlr = *on
c Return
c*
c*
c *PSSR BEGSR
c 'pssr' DSPLY
c move err_excpdata dexcpdata
c exfmt rerr
c 'Line Number' DSPLY
c Err_Linenum DSPLY
c 'Err_Status' dsply
c Err_Status dsply
c 'Err_ProcName'dsply
c Err_ProcName dsply
c 'Err_Routine' dsply
c Err_Routine dsply
c 'Err_ExcpType'dsply
c Err_ExcpType dsply
c 'Err_ExcpNum' dsply
c Err_ExcpNum dsply
c Goto end1
c ENDSR

CLERR Program :

PGM
SNDPGMMSG MSG('THIS IS CLERR.') TOPGMQ(*PRV)
SNDPGMMSG MSGID(CAE0032) MSGF(QCPFMSG) MSGTYPE(*ESCAPE)
WRKSPLF

ENDPGM

OUTPUT :
DSPLY Before
DSPLY pssr

139
RPG-ILE LABS

DSPLY Line Number


DSPLY 00000014
DSPLY Err_Status
DSPLY 202
DSPLY Err_ProcName
DSPLY RPSCAN2
DSPLY Err_Routine
DSPLY CLERR
DSPLY Err_ExcpType
DSPLY CAE
DSPLY Err_ExcpNum
DSPLY 0032
DSPLY After

I tried to see the step by step execution but could not add CLERR program since it is
a OPM program ( Said *YES to OPM source level debugging as well as a *YES to updte
production files) still I cannot add CLERR to the list of programs debugged. When the
CALL statemnt was executed, STRDBG did not show the code or step by step execution of
code in the CLERR program. CLERR was executed instantly and control went directly to
PSSR.

LAB : Error Handling in the procedure

Program P1 created from 2 modules : RPCLIENT and RPAVG :

Listing of RPCLIENT : (Main procedure)

DRslt s 4s 0
DFn1 PR 4s 0
DN1 4s 0
DN2 4s 0
DN3 4s 0
DFn2 PR 4s 0
DN1 4s 0
DN2 4s 0
Da1 s 4s 0 inz(0)
Da2 s 4s 0 inz(0)
Da3 s 4s 0 inz(0)
c
c
C Eval Rslt = Fn1(a1:a2:a3)
C Rslt Dsply
C Eval Rslt = Fn2(a1:a2)
C Rslt Dsply
C Eval *inlr = *on
C Return
C
C

Listing of RPAVG ( NOMAIN Module)

H NOMAIN
dMyds sds
dLnNum 21 28
dStatus *status
d*

140
RPG-ILE LABS

dFn1 PR 4s 0
dx1 4s 0
dy1 4s 0
dz1 4s 0
dFn2 PR 4s 0
dx2 4s 0
dy2 4s 0
dRslt s 4s 0
PFn1 B Export
dFn1 PI 4s 0
dx1 4s 0
dy1 4s 0
dz1 4s 0
c
c z-add *zeros x1
c Eval Rslt = (x1+y1+z1)/x1
c cnt1 Tag
c Return Rslt
c*
c *Pssr Begsr
c 'Pssr1' Dsply
c LnNum Dsply
c Status Dsply
c If LnNum = '00000021'
c Goto cnt1
c Endif
c Endsr
c
PFn1 E
PFn2 B Export
dFn2 PI 4s 0
dx2 4s 0
dy2 4s 0
c z-add *zeros x2
c Eval Rslt = (x2+y2)/x2
c Cnt2 Tag
c Return Rslt
c*
c *Pssr Begsr
c 'Pssr2' Dsply
c If LnNum = '00000040'
c Goto cnt2
c Endif
c Endsr
c
PFn2 E

LAB : Testing correctness of date entered.

Linkage : DSDTDATE, RPDATETEST

CODE :

PROGRAM : RPDATETEST

HDatfmt(*dmy-)
FDsDtTest cf e workstn
dCheckDate PR 5i 0
dto_be_tested 6s 0

141
RPG-ILE LABS

dretval s 5i 0
ddt s 6s 0
c*O
c Dow *in03 = *off
c Exfmt Rec1
c Eval dt = ddt001
c Eval RetVal = CheckDate(dt)
c Select
c when Retval = -1
c Eval dstat = 'Wrong !'
c when Retval = 1
c Eval dstat = 'Correct'
c other
c 'huh ?!' dsply
c endsl
c EndDo
c* -O
c Eval *inlr = *on
c return
c* Check Date procedure
c* ____________________________________________________
PCheckDate B
DCheckDate PI 5i 0
dTestDate 6s 0
dRetVal s 5i 0 inz(0)
c *DMY TEST(D) TestDate 66
c if *in66=*on
c Eval RetVal = -1
c Else
c Eval RetVal = 1
c EndIf
c Return RetVal
PCheckDate E

Display file : DSDTTEST

A DSPSIZ(24 80 *DS3)
A R REC1
A CA03(03)
A WINDOW(2 2 20 40)
A 2 13'Date Test Program'
A 5 5'Enter date to test :'
A DDT001 6Y 0B 7 6COLOR(BLU)
A EDTWRD(' - - ')
A EDTMSK(' & & ')
A 12 7'Status :'
A COLOR(WHT)
A DSTAT 10 O 12 18COLOR(WHT)

PF contents :

nil

OUTPUT :

REMARKS :

142
RPG-ILE LABS

143
RPG-ILE LABS

LAB : /COPY precompiler directive

RP0001 Listing : This program is never compiled. Only used by RP0002 for its
subroutines.

c sr1 begsr
c 'hello' dsply
c endsr

Notice : This is not a Code fragment but a complete program.

RP0002 Listing : This program uses subroutines found in RP0001.

Only RP0002 is compiled.

c exsr sr1
c seton lr
c return
c/COPY SAM2/QRADLE,RP0001

The /Copy should come exactly where you wish to have the code pasted.
Since Subroutines come after SETON LR, I have placed the /COPY after Seton Lr and
RETURN.

LAB : Debugging a copy book.

RP001 Listing :

dn1 s 5i 0 inz(8)
d n2 s 5i 0 inz(100)
drslt s 5i 0
c Eval rslt = n1 + n2
c rslt Dsply
c Exsr SR001
c Eval *inlr = *on
c Return
c/COPY train12/sameerr,rp002

RP002 Listing :

c SR001 BegSr
c 'SR001!' Dsply
c EndSR

Start debugging of RP001 normally.During compilation, set DEBUGGING VIEWS to *ALL or


atleast *COPY. Use Shift + F3 to select views as COPY view.
This will display the source of RP002 where the /COPY was present. You can not use
F10 to step throu the code : even the code copied into the parent program by the
/COPY.

144
RPG-ILE LABS

145
RPG-ILE LABS

LAB : Use of Monitor

Linkage : RPCHAR

CODE :

DN1 s 5i 0 inz(108)
DS1 s 10a
c*
c* %Char converts int to character
c*
c Eval S1 = 'MECH' + %Char(N1)
c S1 Dsply
c*
c* Int converts char to int.
c* ---------------------------
c Monitor
C* Eval statement will definitely cause problem since we are trying to
C* convert non-numeric stuff to numeric.
C* We cannot use (E) as error handler operation extender since
C* E can be used with only those opcodes that allow error indicators (LO )
C*
c Eval N1 = %Int(s1)
c ON-ERROR
c 'Error' Dsply
c Endmon
c*
c*
c N1 Dsply
c Eval *inlr = *on
c Return
c*

PF contents :

---

OUTPUT :

Sensitive stuff (that can cause a run time error) should be placed inside MONITOR and
ENDMON group.If a statement (inside MONITOR group ) fails, control goes into ON_ERROR
and allows you to handle the error.

REMARKS :

MONITOR and ENDMON is a good replacement for *PSSR.

146
RPG-ILE LABS

LAB : MONITOR and ENDMON: How it works. (this is the second lab)

Linkage : RPMON

CODE :

da s 4p 0 inz(10)
db s 4p 0 inz(2)
dc s 4p 0 inz(0)
ds s 4a
c Monitor
c Eval c = a/b
c Eval s = 'c = ' + %Char(c)
c Eval b = 0
c Eval c = a/b
c* the above EVAL throughs an exception
c* which is caught by ON_ERROR
c* the next EVAL statement is never executed
c* -----------------------------------------
c Eval s = 'c = ' + %Char(c)
c On-Error
c 'error !' Dsply
c EndMon
c 'Over' Dsply
c Eval *inlr = *on

PF contents :

---

OUTPUT :

REMARKS :

So long as the statements inside the MONITOR execute correctly, the execution
proceeds step by step. If a statement has a problem, control goes directly into ON-
ERROR skipping all the intermediate statements.

147
RPG-ILE LABS

LAB : HUB coding snippets

What is the output of the following code ?

dnum1 s 5i 0 inz(100)
c do 2
c If jsrvar <>12
c 'not 12' dsply
c z-add 12 jsrvar 5 0
c EndIf
c jsrvar Dsply
c EndDo
c Eval *inlr = *on

OUTPUT :

DSPLY not 12
DSPLY 12
DSPLY 12

LAB : HUB code sample

dnum1 s 5i 0 inz(100)
c do 2
c If jsrvar <>12
c 'not 12' dsply
c z-add jsrvar jsrvar 5 0
c EndIf
c jsrvar Dsply
c EndDo
c Eval *inlr = *on

OUTPUT :
DSPLY not 12
DSPLY 0
DSPLY not 12
DSPLY 0

148
RPG-ILE LABS

149
RPG-ILE LABS

LAB : DataQ Programming

dDQName s 10a inz('DTA2')


dDQLib s 10a inz('SAM2')
dDQLen s 5p 0 inz(10)
dDQData s 10a inz('JSR')
dDQWait s 5p 0 inz(10)
c P1 Plist
c Parm DQName
c Parm DQLib
c Parm DQLen
c Parm DQData
c Call 'QSNDDTAQ' P1
c Eval DQData = *all'*'
C*
c Call 'QRCVDTAQ'
c Parm DQName DQName
c Parm DQLib DQLib
c Parm DQLen DQLen
c Parm DQdata DQData
c Parm DQWait DQWait
c 'recd : ' Dsply
c DQData Dsply
c Eval *inLr = *on
c Return

150
RPG-ILE LABS

LAB : WOKRING ON SPACEA

CREATE A REPORT WITH NO SPACEA OR SPACEB FOR A RECORD FORMAT. WRITE A PROGRAM TO DO
MULTIPLE WRITE STATEMENTS TO THE RECORD FORMAT, YOU WILL FIND THAT THE LINES WILL BE
OVERWRITTEN.RLU DOES NOT AUTOMATICALLY PUT A LINE BETWEEN 2 WRITE OPERATIONS WHEN IT
COMES TO RECORD FORMAT OF A REPORT

FRL001 O E PRINTER
C WRITE RREC1
C WRITE RREC1
C WRITE RREC1
C WRITE RREC1
C WRITE RREC1
C EVAL *INLR = *ON
C RETURN

LISTING OF THE REPORT FILE :

A R RREC1
A SPACEA(1)
A 4
A 'THIS IS A TEST'
A +8
A 'ONE MORE'

SPACEA CAN BE USED AT THE RECORD LEVEL AS WELL AS FIELD LEVEL.

Lab : Working on SKIPA

Report DDS :

A R RREC1
A 4'THIS IS A TEST'
A SPACEA(1)
A SKIPA(15)
A +8'ONE MORE'

After This is a TEST is printed on paper, a 1 line space is put. After that,
the paper slips straight to line 15, if LINE 15 found on the same page printing
continues on that page. If line 15 is already passed, system ejects current page and
continues printing from line 15 on the next page.

LAB : Writing codes to printer files (Hex)

FRLHEX O E PRINTER
C write RHEX
C SETON LR

RLHEX Listing :

A R RHEX

151
RPG-ILE LABS

A 3
A ' '
A SPACEA(1)
A 15DFT(X'33') TRNSPY
A 17DFT(X'7C') TRNSPY

NOTE : X’33 produces a block

X’7C’ produces @ sign.

LAB : Printing a Line in report

A R RHEX
A LINE(6.0 6.1 2 *HRZ 1)

Compile using Printer type as *SFPDS (Advanced Function Printer Data Stream) not IPDS
(intelligent Printer Data Stream)

LAB : Page rotation

A R RHEX PAGRTT(90)
A 5'HELLO'
A 11'WORLD'
Lab : CPI

A R RHEX LPI(9)
A 5'HELLO'
A 11'WORLD'

LAB : Resetting the Page number

A R RDETL
A SPACEA(001)
A 3
A ' '
A PFLD1 4S 0 16
A R RPAGE
A 70
A 'PG '
A 75
A 78 PAGNBR
A EDTCDE(Z)

Program To reset page numbers every 5 pages :

(you’ll never get page #6, it will always be 1 2 3 4 5 1 2 3 4 5 etc)

FRLHEX O E PRINTER OFLIND(*in77)


DCntr s 4s 0 inz(0)
DPageNumber s 4s 0 inz(0)
d*
c Do 668
c Eval Cntr = Cntr + 1
c Eval PFLD1 = cntr
C write RDetl
c If *in77= *on

152
RPG-ILE LABS

c Eval *IN77 = *off


c Eval PageNumber = PageNumber + 1
c If PageNumber > 5
c Eval *in78 = *on
c Write RPage
c Eval *in78 = *off
c else
c Write RPage
c endif
c Endif
c Enddo
C SETON LR

LAB : POSITION keyword to place text at the right place on the paper

FRLpos O E PRINTER
dps s 4s 0 inz(12)
dpos1 s 5s 3 inz(2.00)
dpos2 s 5s 3 inz(3.00)
c Eval rfld1=ps
c Eval fld1=pos1
c Eval fld2=pos2
c write rpos
C SETON LR

Report :

A R RPOS
A RFLD1 4S 0 POSITION(&FLD1 &FLD2)
A FLD1 5S 3P
A FLD2 5S 3P

Please compile the report file with the device option set to
*AFPDS (Adv printing Function Data Stream)

OUTPUT :

File . . . . . : RLPOS Page/Line 1/12


Control . . . . . Columns 1 - 78
Find . . . . . .
*...+....1....+....2....+....3....+....4....+....5....+....6....+....7.
0012

LAB : Specify Font


QFNTCPL/QSYS

A R RDETL
A CDEFNT(QFNTCPL/X0BITR)
A SPACEA(001)
A 3
A ' '
A PFLD1 4S 0 16
A R RPAGE
A 70
A 'PG '
A 75

153
RPG-ILE LABS

A 78 PAGNBR
A EDTCDE(Z)

RPG pprogram listing remains the same. Device type should not be anything other that
AFPDS.

LAB : Specify font and point size

A R RDETL FONT(16951 (*POINTSIZE 10))


A SPACEA(001)
A 3
A ' '
A PFLD1 4S 0 16FONT(222)
A R RPAGE
A 70
A 'PG '
A 75
A 78 PAGNBR
A EDTCDE(Z)

LAB : indara

Functionally no effect of Indara on display file record format.

A DSPSIZ(24 80 *DS3)
A INDARA
A CA03(03)
A R RINDARA
A* OVERLAY
A CF07(07)
A 4 10'INDARA REC FMT'
A COLOR(WHT)
A R RINDARA1
A* OVERLAY
A CF07(08)
A 8 10'INDARA 1 '
A COLOR(RED)

FDSIndara CF E WORKSTN
c Dow *in03 = *off
c Write Rindara
c*** Write Rindara1
c Read Rindara 55
c Exsr ChkSR
c* Write Rindara
c Write Rindara1
c Read Rindara1 55
c Exsr ChkSR1
c Enddo
C Eval *inlr = *on
C Return
C*
C ChkSR Begsr
c 'INDARA :' dsply
C if *in07 = *on
c '07 ' dsply
c Endif
C if *in08 = *on

154
RPG-ILE LABS

c '08 ' dsply


c Endif
c* Eval *in07=*off
c* Eval *in08=*off
c Endsr
c*
C ChkSR1 Begsr
c 'INDARA 1 :' dsply
C if *in07 = *on
c '07 ' dsply
c Endif
C if *in08 = *on
c '08 ' dsply
c Endif
c* Eval *in07=*off
c* Eval *in08=*off
c Endsr

Tried adding and removing indara but no change in beh.

Both rec fmt share the indicators.


If 07 is ONed when one rec fmt is displayed, it is ON for the second rec fmt as and
when it is displayed.
Here I swicthed ON ind 07 when RINDARA was displayed, when I did EXFMT for rINDARA1,
07 was ON. If I again press F7 for RINDARA1, 08 becomes ON (in addition to 07)

If you press ENTER (and not any of the mapped function key), all indicators are
turned off. IN the next interation, both 07 and 08 are automatically OFF (don’t have
to be turned of explicitly).

LAB : Working with POSITION Keyword

A R RPOS
A PCHAR 4A
A POSITION(&FLD1 &FLD2)
A FLD1 5S 3P
A FLD2 5S 3P
A*

FRLpos O E PRINTER
dn1 s 5s 3 inz(1)
dn2 s 5s 3 inz(1)
d*
c Eval n1 = n1 + 1
c Eval n2 = n2 + 0.5
c Eval fld1 = n1
c Eval fld2 = n2
c write rpos
c Eval n1 = n1 + 1
c Eval n2 = n2 + 0.5
c Eval fld1 = n1
c Eval fld2 = n2
c write rpos
C SETON LR

155
RPG-ILE LABS

This worked , but no Preview or spool file is displayed although it is created. The
system gives error message that the spool file contains Graphics data which cannot be
displayed.
Only sol is to take a physical printout.

156
RPG-ILE LABS

LAB : Dynamic positioning of window using Program-to-system fields

FDSWINTRY cf E workstn
DStartLine s 3s 0 inz(3)
DStartPosition s 3s 0 inz(3)
DTempNum s 3s 0 inz(0)
D*
C Eval StLine = StartLine
C Eval StPos = StartPosition
C exfmt Rwin
C Eval StartLine = 3
C Eval StartPosition = 30
C Eval StLine = StartLine
C Eval StPos = StartPosition
C Exfmt Rwin
C Eval *inlr = *on
C Return

Display file :

A DSPSIZ(24 80 *DS3)
A R RWIN
A WINDOW(&STLINE &STPOS 9 9)
A STLINE 3S 0P
A STPOS 3S 0P
A FLD001 4 B 2 2
A FLD002 4 0B 4 2
A FLD003 4 B 6 2
A FLD004 4 0B 8 2
A 1 2'test Scr'
A DSPATR(UL)

LAB : RMVWDW : remove previously displayed windows when displaying current window.

A DSPSIZ(24 80 *DS3)
A R RWIN
A WINDOW(&STLINE &STPOS 9 9)
A RMVWDW
A STLINE 3S 0P
A STPOS 3S 0P
A FLD001 4A B 2 2
A FLD002 4S 0B 4 2
A FLD003 4A B 6 2
A FLD004 4S 0B 8 2
A 1 2'test Scr'
A DSPATR(UL)
FDSWINTRY cf E workstn
DStartLine s 3s 0 inz(3)
DStartPosition s 3s 0 inz(3)
DTempNum s 3s 0 inz(0)
D*
C Eval StLine = StartLine
C Eval StPos = StartPosition
C exfmt Rwin
C Eval StartLine = 3

157
RPG-ILE LABS

C Eval StartPosition = 30
C Eval StLine = StartLine
C Eval StPos = StartPosition
C Exfmt Rwin
C Eval *inlr = *on
C Return

Student Example : Moving the window leftwards when F1 is pressed

fdstry cf e workstn
dn1 s 4s 0 inz(1)
c Eval stpos = 4
c Eval stlin = 3
c Dow *in03=*off
c write rwin
c exfmt rnormal
c if *in01 = *on
c Eval stpos = stpos +1
c Eval *in01 = *off
c Endif
c Enddo
c Eval *inlr = *on
c Return

A DSPSIZ(24 80 *DS3)
A R RNORMAL WINDOW(RWIN)
A CF01(01)
A CA03(03)
A 6 15'this is a normal record format’
A R RWIN
A WINDOW(&STLIN &STPOS 19 45)
A STLIN 3S 0P
A STPOS 3S 0P

LAB : How to display a Display file record format without the mandatory READ
operation on its record format

PART 1 :

FDSB00 CF E WORKSTN
C WRITE RB00
C 'HELO' DSPLY
C WRITE RB00
C SETON LR
C RETURN

The above code actually displays the display file record format, although there is no
READ operation. This is possible by setting the DFRWRT = *NO (defer write) during
Display file compilation.

PART 2 :

Same effect can be achieved by using FRCDTA (Force data) record level keyword.

A DSPSIZ(24 80 *DS3)
A R RBASE
A CA03(03)

158
RPG-ILE LABS

A FRCDTA
A 4 9'THIS IS A TEST OF BOO'
A 7 10'CODE :'
A 9 10'NAME :'
A 11 10'ADDRESS : '
A FLD1 4S 0B 7 21
A FLD2 20A B 9 21
A FLD3 30A B 11 21
A FLD4 30A B 12 21
A FLD5 30A B 13 21
A R RWIN
A CA12(12)
A WINDOW(4 50 9 9)
A OVERLAY
A FLD001 3 B 1 2
A FLD002 3 0B 3 2
A FLD003 2 0B 4 2

Rpgle :

FDSB00 CF E WORKSTN
C WRITE RBASE
C EXFMT RWIN
C WRITE RBASE
C WRITE RWIN
C READ RBASE 44
C SETON LR
C RETURN

LAB : csrloc TO POSITION THE CURSOR WHEN THE RECORD FORMAT IS BIEND DISPLAYED

FDSB00 CF E WORKSTN
C EVAL L = 9
C EVAL P = 21
C EXFMT RBASE
C SETON LR
C RETURN

DISPLAY FILE LISTING :

A DSPSIZ(24 80 *DS3)
A R RBASE CSRLOC(L P)
A CA03(03)
A FRCDTA
A L 3S 0H
A P 3S 0H
A 4 9'THIS IS A TEST OF BOO'
A 7 10'CODE :'
A 9 10'NAME :'
A 11 10'ADDRESS : '
A FLD1 4S 0B 7 21
A FLD2 20A B 9 21
A FLD3 30A B 11 21
A FLD4 30A B 12 21
A FLD5 30A B 13 21

159
RPG-ILE LABS

LAB : CHECK(ER) to make Field Exit key work like ENTER key

It is recommended to use CHECK(ER) on the last field of the Display file. After data
entry operator has typed data into the last data field and pressed Field exit, he
need no press ENTER again to pass control into RPG. Then Field Exit is pressed for
the last field, it is works like ENTER because this field has CHECK(ER).

A DSPSIZ(24 80 *DS3)
A CA03(03)
A R RERASE
A 5 7'code : '
A 7 7'Name :'
A 9 7'Address :'
A FLD001 4S 0B 5 19
A FLD002 10A B 7 19
A FLD003 40A B 9 19
A FLD004 40A B 10 19
A 18 4'SAVE ? '
A FLD005 1A B 18 19CHECK(ER)
fdserase cf e workstn
c Exfmt RErase
c fld001 dsply
c Exfmt RErase
c fld001 dsply
c Exfmt RErase
c fld001 dsply
c Eval *inlr = *on
c Return

code : 2

Name : AMIT

Address : 4,KNABLE LANE, TRAVOSE


CALIFORNIA

SAVE ? Y

When User enters Y in the Save field, control immediately returns to RPG for further
operation.

Lab : CHECK(VN) TO VALIDATE A SIMPLE NAME. CHECK(VNE) TO VALIDATE A NAME (EXTENDED)

A DSPSIZ(24 80 *DS3)
A CA03(03)
A R RERASE
A 5 7'code : '

160
RPG-ILE LABS

A 7 7'Name :'
A 9 7'Address :'
A FLD001 4S 0B 5 19
A FLD002 10A B 7 19
A CHECK(VN)
A FLD003 40A B 9 19
A FLD004 40A B 10 19
A 18 4'SAVE ? '
A FLD005 1A B 18 19CHECK(ER)
fdserase cf e workstn
c Exfmt RErase
c fld001 dsply
c Exfmt RErase
c fld001 dsply
c Exfmt RErase
c fld001 dsply
c Eval *inlr = *on
c Return

CHECK(VN) is for validation of NAME of a object / person :

It checks basic things like :

1. Name cannot contain symbols except #


2. Name should not contain embedded spaces.

LAB : Overlapping record formats & application of CLRL.

Display file listing (pay attention to the positions of the lines of the 2 record
formats. You will se that the the record formats overlap. Depending on need, one or
both can be displayed although only 1 will be in the READ mode)

CLRL (2) is specified for R1 record format.When R1 is displayed, All lines occupied
by R1 are first cleared. Since value specified CLRL is 2, a minimum of 2 lines will
be cleared. This last portion (last 2-3 lines) of RERASE is dislpayed
Even when an EXFMT is done to R1.

CLRL(*END) will clear all lines after 1st line of R1.

A DSPSIZ(24 80 *DS3)
A CA03(03)
A R RERASE
A OVERLAY
A 5 7'code : '
A 7 7'Name :'
A 9 7'Address :'
A FLD001 4S 0B 5 19TEXT('CODE VALUE')
A FLD002 10A B 7 19CHECK(VNE)
A FLD003 40A B 9 19
A FLD004 40A B 10 19
A 17 4'REC FMT 1'
A 18 4'SAVE ? '
A FLD005 1A B 18 19CHECK(ER)
A R R1 CLRL(2)
A OVERLAY
A 9 7'XXXXXXX'
A COLOR(RED)

161
RPG-ILE LABS

A 10 7'YYYYYYY'
A COLOR(RED)
A 11 7'ZZZZZZZ'
A COLOR(RED)
A FLD1 40A B 12 19
A COLOR(RED)
A FLD2 40A B 13 19
A COLOR(RED)
A 14 4'REC FMT 2'
A COLOR(RED)
RPGLE:

fdserase cf e workstn
c exfmt r1
c Exfmt RErase
c fld001 dsply
c exfmt r1
c Exfmt RErase
c fld001 dsply
c exfmt r1
c Exfmt RErase
c fld001 dsply
c Eval *inlr = *on
c Return

OUTPUT :

code : 1

Name : ANIL

XXXXXXX
YYYYYYY
ZZZZZZZ
TEST
DATA
REC FMT 2

REC FMT 1
SAVE ? Y

LAB : Study of CHANGE keyword

A DSPSIZ(24 80 *DS3)
A R RCHANGE
A CA03(03)
A 6 6'ARG1 : '
A COLOR(BLU)
A 8 6'ARG2 : '
A COLOR(BLU)
A 10 6'ARG3 :'
A COLOR(BLU)
A DARG1 4 0B 6 16COLOR(WHT)
A CHANGE(20)

162
RPG-ILE LABS

A DARG2 4 0B 8 16COLOR(WHT)
A CHANGE(21)
A DARG3 4 0B 10 16COLOR(WHT)
A CHANGE(22)

FDSCHANGE CF E WORKSTN
C Dow *in03 = *off
C Exfmt rchange
C *in20 Dsply
C *in21 Dsply
C *in22 Dsply
C Setoff 202122
C Enddo
C Eval *inlr= *on
C Return

CHANGE Indicator is set on when :

1. Field Exit is pressed in a field


2. Some data is typed followed by field exit
3. existing data is changed

LAB : Detailed work on edit code

| 4.1.1.5 %EDITC (Edit Value Using an Editcode)

| %EDITC(numeric : editcode {: *ASTFILL | *CURSYM | currency-symbol})

| This function returns a character result representing the numeric value


| edited according to the edit code. In general, the rules for the numeric
| value and edit code are identical to those for editing numeric values in
| output specifications. The third parameter is optional, and if specified,
| must be one of:

| *ASTFILL Indicates that asterisk protection is to be used. This means


| that leading zeros are replaced with asterisks in the returned
| value. For example, %EDITC(0012.5 : 'K' : *ASTFILL) returns
| '***12.5-'.

| *CURSYM Indicates that a floating currency symbol is to be used. The


| actual symbol will be the one specified on the control
| specification in the CURSYM keyword, or the default, '$'. When
| *CURSYM is specified, the currency symbol is placed in the the
| result just before the first significant digit. For example,
| %EDITC(0012.5 : 'K' : *CURSYM) returns ' $12.5-'.

| currency-symbol Indicates that floating currency is to be used with the


| provided currency symbol. It must be a 1-byte character constant
| (literal, named constant or expression that can be evaluated at
| compile time).

| Float expressions are not allowed in the first parameter (you can use %DEC
| to convert a float to an editable format). The edit code is specified as
| a character constant; supported edit codes are: 'A' - 'D', 'J' - 'Q', 'X'
| - 'Z', '1' - '9'. The constant can be a literal, named constant or an
| expression whose value can be determined at compile time.

Subtopics

163
RPG-ILE LABS
4.1.1.5.1 %EDITC Examples
4.1.1.5 - 1
%EDITC Examples
| 4.1.1.5.1 %EDITC Examples

--------------------------------------------------------------------------

| D msg S 100A
| D salary S 9P 2

| * If the value of salary is 2451.53, then the value of salary * 12


| * is 29418.36. The edited version of salary * 12 using the A edit
| * code with floating currency is ' $29,418.36 '.
| * The value of msg is 'The annual salary is $29,418.36'
| C EVAL msg = 'The annual salary is '
| C + %trim(%editc(salary * 12
| C :'A': *CURSYM))

| * If the value of salary is 2451.53, then the value of salary * 12


| * is 29418.36. The edited version of salary * 12 using the A edit
| * code with floating currency is ' $29,418.36 '.
| * The value of msg is 'The annual salary is &29,418.36'
| C EVAL msg = 'The annual salary is '
| C + %trim(%editc(salary * 12
| C :'A': '&'))

| * In the next example, the value of msg is 'Salary is $***29,418.36'


| * Note that the '$' comes from the text, not from the edit code.
| C EVAL msg = 'Salary is $'
| C + %trim(%editc(salary * 12
| C :'B': *ASTFILL))

| * In the next example, the value of msg is 'The date is 1996/06/27'


| C EVAL msg = 'The date is '
| C + %trim(%editc(*date : 'Y'))

--------------------------------------------------------------------------
| Figure 125. %EDITC Example 1

| A common requirement is to edit a field as follows:

| _ Leading zeros are suppressed


| _ Parentheses are placed around the value if it is negative

| The following accomplishes this using an %EDITC in a subprocedure:

--------------------------------------------------------------------------

| D neg S 5P 2 inz(-12.3)
| D pos S 5P 2 inz(54.32)
| D editparens PR 50A
| D val 30P 2 value
| D editedVal S 10A

| C EVAL editedVal = editparens(neg)


| * Now editedVal has the value '(12.30) '
| C EVAL editedVal = editparens(pos)
| * Now editedVal has the value ' 54.32 '
4.1.1.5.1 - 1
%EDITC Examples

| *---------------------------------------------------------------
| * Subprocedure EDITPARENS
| *---------------------------------------------------------------
| P editparens B
| D editparens PI 50A

164
RPG-ILE LABS
| D val 30P 2 value
| D lparen S 1A inz(' ')
| D rparen S 1A inz(' ')
| D res S 50A

| * Use parentheses if the value is negative


| C IF val < 0
| C EVAL lparen = '('
| C EVAL rparen = ')'
| C ENDIF

| * Return the edited value


| * Note that the '1' edit code does not include a sign so we
| * don't have to calculate the absolute value.
| C RETURN lparen +
| C %editc(val : '1') +
| C rparen

| P editparens E

LAB : Indicator Data structure

FMySUBFILE4 CF E WORKSTN INFDS(DSINF001)

D RRN S 5 0
DDSINF001 DS
DKEYIN 369 369
DENTER C CONST(X'F1')

:
:
:

C IF KEYIN = ENTER
C // Code

165
RPG-ILE LABS

Example program :

FDSINDDS CF E WORKSTN INFDS(DS001)


DDS001 DS
DINKEY 369 369
DENTER C CONST(X'F1')
DF3 C CONST(X'33')
DF4 C CONST(X'34')
DF5 C CONST(X'35')
C EXFMT R1
C IF INKEY = ENTER
C 'ENTER' DSPLY
C Endif
C*
C IF INKEY = F3
C 'F3 ' DSPLY
C Endif
C IF INKEY = F4

REF :
***********************************************************

D F1 C CONST(X'31')
D F2 C CONST(X'32')
D F3 C CONST(X'33')
D F4 C CONST(X'34')
D F5 C CONST(X'35')
D F6 C CONST(X'36')
D F7 C CONST(X'37')
D F8 C CONST(X'38')
D F9 C CONST(X'39')
D F10 C CONST(X'3A')
D F11 C CONST(X'3B')
D F12 C CONST(X'3C')
D F13 C CONST(X'B1')
D F14 C CONST(X'B2')
D F15 C CONST(X'B3')
D F16 C CONST(X'B4')
D F17 C CONST(X'B5')
D F18 C CONST(X'B6')
D F19 C CONST(X'B7')
D F20 C CONST(X'B8')
D F21 C CONST(X'B9')
D F22 C CONST(X'BA')
D F23 C CONST(X'BB')
D F24 C CONST(X'BC')
D CLEAR C CONST(X'BD')
D ENTER C CONST(X'F1')
D HELP C CONST(X'F3')
D ROLLDN C CONST(X'F4')
D ROLLUP C CONST(X'F5')
D PRINT C CONST(X'F6')
D RCBKSP C CONST(X'F8')
D AUTENT C CONST(X'3F')
D WSDS DS
D functionKey 369 369
END

166
RPG-ILE LABS

LAB : KA and KB indicators

Listing :-

FDStestF cf e workstn
c Exfmt R1
c If *inka = *on
c 'KA on !' dsply
c Endif
c
c If *inkb = *on
c 'KB on !' dsply
c Endif
c eval *inlr = *on

The display file DSTestF has CA01(01) and CA02(02) at the file level.
When user presses F1, the corresponding indicator KA is switched on.Similarly for F2
and KB.

END

167
RPG-ILE LABS

LAB : CHECKMSGID FOR VALIDATION OF DATA INPUT BY USER.

First Give A CHECK or RANGE condition for validation, then follow that by a
CHECKMSGID (<msg id> <lib>/<msg file name>)

First create a Message File called MSGF1 in SAM2 and add 2 messages with IDs MSG001
and MSG002.

DISPLAY FILE LISTING

A DSPSIZ(24 80 *DS3)
A R RVLD
A CA03(03)
A 5 17'ENTER A VALUE BETWEEN 100 & 200’
A 7 17'DATA : '
A FLD001 4S 0B 7 27COLOR(WHT)
A RANGE(100 200)
A CHKMSGID(MSG0001 SAM2/MSGF1)
A FLD002 1A B 11 18

RPGLE LISTING

FDSVLD CF E WORKSTN
C EXFMT RVLD
C SETON LR
C RETURN

LAB : ERRMSGId

FDSVLD CF E WORKSTN
C EXFMT RVLD
c* 10 corresp to
c* ERRMSGID
c*
c Eval *in10 = *on
C EXFMT RVLD
C SETON LR
C RETURN

Display Message File :

A DSPSIZ(24 80 *DS3)
A R RVLD
A CA03(03)
A 517'ENTER A VALUE BETWEEN 100
A 617'OR BETWEEN 400 AND 500'
A 817'DATA : '
A FLD001 4S 0B 927COLOR(WHT)
A 10 ERRMSGID(MSG0002 *LIBL/MSGF1)
A FLD002 1A B 11 18

AS SETON 10 and EXFMT is done, the Error Message is loaded from the Message File and
displayed on the screen. The keyboard is locked and waits for Reset key to be
pressed.

168
RPG-ILE LABS

LAB : SENDING PROGRAM VARIABLES IN PRE-DEFINED MESSAGES

IN THE MESSAGE FILE MSGF1 ADD A MESSAGE MSG0003


AS FOLLOWS :

THE VALUE OF N IS &1

IN THE NEXT SCREEN SPECIFY THE FIRST DATA VARIABLE AS *CHAR WITH LEN 4 AND DEC POS 0
(!)

SAVE AND EXIT

THE FOLLOWING CL PROGRAM WRITES RUN TIME VALUES INTO THE PRE-DEFINED MESSAGE.
:

PGM
DCL &N TYPE(*DEC) LEN(4 0) VALUE(123)
DCL &SN TYPE(*CHAR) LEN(4)
CHGVAR VAR(&SN) VALUE(&N)
SNDPGMMSG MSGID(MSG0003) MSGF(SAM2/MSGF1) MSGDTA(&SN)
ENDPGM

RPGLE EQIUIVALENT :

The Display file contains CHKMSGID (MSG0003 SAM2/MSGf1 &CNTR)

The Message MSG0003 has 1 variable field ( identified as &1 ) which was defined as
*CHAR with size 4 and dec pos 0 . here the RPGLE program specifies this message in
the CHKMSGID keyword. RPGLE makes sure that value of the variable CNTR is et to some
valid value before record format is displayed on the screen.

Message File listing :

MSGID > MSG0003


MSGF > MSGF1
> SAM2
MSG 'the value of N is &1'

Message data fields formats: FMT


Data type . . . . . . . . . . *CHAR
Length . . . . . . . . . . . . 4
*VARY bytes or dec pos . . . . 0
+ for more values _

If you press + in the underline above, you can specify more fields.

Dislpay File Listing :

A DSPSIZ(24 80 *DS3)
A R RVLD
A CA03(03)
A CNTR 4A P
A 5 17'ENTER A VALUE BETWEEN 100
A 6 17'OR BETWEEN 400 AND 500'
A 8 17'DATA : '
A FLD001 4S 0B 9 27COLOR(WHT)

169
RPG-ILE LABS

A RANGE(100 200)
A CHKMSGID(MSG0003 SAM2/MSGF1 &CNTR)
A FLD002 1A B 11 18

FDSVLD CF E WORKSTN
c EVAL CNTR='123'
C EXFMT RVLD
C
C SETON LR
C RETURN

LAB : Multiple values displayed on Pre-defined messages

Message details : Tried to put many variables into 1 message but wont work with
ERRMSGID. ERRMSGID can take ERRMSGID(MSG0099 MSGF1 &STR)
But not
ERRMSGID(MSG0099 MSGF1 &x &y &z)

ie ERRMSGID does not take more than 1 variables as values to the keyword.
I wanted to display something like this :

A = 10 B = 12 . their Sum is 22.


For putting the 3 values, I initially created a message with 3 variable, but knowing
the limitation of ERRMSGID, I created a general purpose Message : MSG0099 that simply
dislpays 1 string as follows :

Message ID . . . . . . . . . : MSG0099
Message file . . . . . . . . : MSGF1
Library . . . . . . . . . : SAM2

Decimal
Field Data Type Length Positions
&1 *CHAR 75

this message contains no text only 1 variable : &1 which I s*CHAR and 75 in length
(roughly 1 row )
What ever u wish to write as a message is dumped into this variable.

The message is displayed via ERRMSGID as seen clearly in the following display file
listing :

Display file details :

A DSPSIZ(24 80 *DS3)
A R RVLD
A CA03(03)
A STR 75A P
A 8 17'DATA : '
A FLD001 4S 0B 9 27COLOR(WHT)
A 10 ERRMSGID(MSG0099 MSGF1 &STR)
A FLD002 1A B 11 18

RPGLE program :

170
RPG-ILE LABS

FDSVLD CF E WORKSTN
DN1 S 4S 0 INZ(122)
DN2 S 4S 0 INZ(16)
DTOTAL s 7s 0 inz(0)
DSN1 s 4a
DSN2 s 4a
DSTOTAL s 7a
d*
c EVAL TOTAL = N1 + N2
C Movel Total sTotal
C Movel N1 sN1
C Movel N2 sN2
c Eval Str = 'A = ' + SN1 + ' B = ' + SN2 + ' .'
c + 'Their Sum : ' + STotal
C EXFMT RVLD
C Eval *in10 = *ON
C EXFMT RVLD
C SETON LR
C RETURN

STR is a program to system variable which is passed to the MSG0099. RPGLE program
writes suitable text into this STR string and sets ON indicator 10. In the next WRITE
operation, the message is displayed on the screen. The message goes when RESET (left
CTRL key) is pressed.

* * *

171
RPG-ILE LABS

LAB : PSDS : General purpose Error DS

DArg1 s 4s 0 inz(-2)
DArg2 s 4s 0 inz(0)
DRslt s 4s 0 inz(0)
D
D
D SDS
D* ---------------------------------------
D* FOR PROCEDURE NAME/PROG NAME
D* YOU CAN SPECIFY EITHER 1 TO 10 OR *PROC
D* ---------------------------------------
DPGMNAM *PROC
DSTS *STATUS
DSRCLIN 21 28
DNUMPAR 37 39
DEXCTYP 40 42
DEXCNUM 43 46
DLIBNAM 81 90
DSRCFNAM 304 313
DSRCLIB 314 323
DSRCMEM 324 333
DPRONAM 334 343
DMODNAM 344 353
c
c 'aaa' Dsply
c Eval Rslt = Arg1/Arg2
c cnt1 Tag
c 'bbb' Dsply
c Eval *inlr = *on
c Return
c
c *PSSR Begsr
C PGMNAM DSPLY
C STS DSPLY
C PGMNAM DSPLY
C STS DSPLY
C SRCLIN DSPLY
C NUMPAR DSPLY
C EXCTYP DSPLY
C EXCNUM DSPLY
C LIBNAM DSPLY
C SRCFNAM DSPLY
C SRCLIB DSPLY
C SRCMEM DSPLY
C PRONAM DSPLY
C MODNAM DSPLY
c Goto cnt1
C Endsr

Variable Value Remarks


PGMNAM RPBMAST
STS 102 Devide by Zero
PGMNAM RPBMAST
SRCLIN 00000025 Devide by zero occurred on line 25 of source code
NUMPAR 000 Number of parameters provided to this program
when it was called

172
RPG-ILE LABS

EXCTYP MCH Exception Type (MCH for Machine Exception)


EXCNUM 1211 Exception number
LIBNAM SAM2 Lib in which this prog is running
SRCFNAM QRADLE002 Source PF of the source code of this program
SRCLIB SAM2
SRCMEM RPBMAST
PRONAM RPBMAST Procedure name in which this procedure is present
(not applicable here)
MODNAM RPBMAST (Module name in which this procedure is present)

LAB : Status codes displayed by PSDS

Following program illustrates the error codes for 2 aritmentic errors :

DIV by ZERO
And
SQRT of a NEGATIVE NUMBER

DErrNum s 6s 0 inz(0)
DArg1 s 6s 0 inz(-4)
DArg2 s 6s 0 inz(0)
DRslt s 6s 0 inz(0)
DSErrNum s 6a
D
D
D SDS
D* ---------------------------------------
D* FOR PROCEDURE NAME/PROG NAME
D* YOU CAN SPECIFY EITHER 1 TO 10 OR *PROC
D* ---------------------------------------
DPGMNAM *PROC
DSTS *STATUS
DSRCLIN 21 28
DEXCTYP 40 42
DEXCNUM 43 46
c
c '1.' Dsply
c Eval Rslt = Arg1/Arg2
c cnt1 Tag
c '2. ' Dsply
c SQRT Arg1 Rslt
c cnt2 Tag
c '---------' Dsply
c Eval *inlr = *on
c Return
c
c *PSSR Begsr
C STS DSPLY
C SRCLIN DSPLY
C EXCTYP DSPLY
C EXCNUM DSPLY
c Select
c When SrcLin='00000020'
c Goto Cnt1
c When SrcLin='00000023'
c Goto Cnt2
c EndSl
c EndSR

173
RPG-ILE LABS

OUTPUT :

DSPLY 1.
DSPLY 102
DSPLY 00000020
DSPLY MCH
DSPLY 1211
DSPLY 2.
DSPLY 101
DSPLY 00000023
DSPLY RNX
DSPLY 0101
DSPLY ---------

LAB : PSDS : More error codes

H DatFmt(*DMY)
D*
D* Mydate is an impossible date
D* ----------------------------
DMydate S 6s 0 INZ(310204)
DMyDate1 s D inz(D'12/04/04')
D
D
D SDS
D* ---------------------------------------
DSTS *STATUS
DSRCLIN 21 28
DEXCTYP 40 42
DEXCNUM 43 46
c
c
c* This data area does not Exist
c* -----------------------------
c
C *DTAARA DEFINE DataArea1 5
c
c
c '1.' Dsply
c *DMY Move MyDate MyDate1
c cnt1 Tag
c '2. ' Dsply
c Call 'NoExist'
c cnt2 Tag
c '3.' Dsply
c *LOCK IN DataArea1
c OUT DataArea1
c UnLock Dataarea1
c cnt3 Tag
c Eval *inlr = *on
c Return
c
c *PSSR Begsr
C STS DSPLY
C SRCLIN DSPLY
C EXCTYP DSPLY
C EXCNUM DSPLY
c Select
c When SrcLin='00000024'
c Goto Cnt1

174
RPG-ILE LABS

c When SrcLin='00000027'
c Goto Cnt2
c When SrcLin='00000030'
c Goto Cnt3
c EndSl
c EndSR

OUTPUT :

DSPLY 1.
DSPLY 112
DSPLY 00000024
DSPLY RNX
DSPLY 0112
DSPLY 2.
DSPLY 211
DSPLY 00000027
DSPLY MCH
DSPLY 3401
DSPLY 3.
DSPLY 401
DSPLY 00000030
DSPLY CPF
DSPLY 1015

Error Code Description


00100 Out of range
00101 Attempted SQRT of a negative number
00102 Div by zero
00112 Invalid date , time or timestamp
00122 OCCUR outside range
00211 Error calling program/procedure
00222 Pointer/Parameter error
00401 Data area specified in the IN/OUT oprn not
found
00411 Data area type/len does not match
00412 Data area not locked for O/P
00414 Not authorised to use data area
00421 Error on UNLOCK oprn
00431 Data area previously locked by another
program
00432 Data area previously locked by program in
the same process
00907 Decimal data error
00803 Rollback Failed
00804 Commit Failed
00802 Commitment control not active
09999 Internal failure

LAB : INFDS Data for a DISK file

Following program creates error condition by tring to open a file twice.Proggram also
illustrates how the error can be corrected.

FPFBMAST UF E DISK USROPN infds(dsBMast)


F infsr(srBMast)
DMsg s 50a
d*
DDsBMast DS

175
RPG-ILE LABS

DIsOpn 9 9
DIsEOF 10 10
DStatus 11 15 0
DOpCode 16 21
DMsgNbr 46 52
c*
c* ------------------------------------------
C 'OPEN NOW...' DSPLY
C Open pfBMAST 77
C If *IN77
C 'CANNOT OPEN' DSPLY
C Eval *inlr = *on
C Return
C Endif
C* ----------------------------------------------
c* Try to open again. Will obviously Fail.
c* ----------------------------------------------
C Open pfBMAST 77
c If *in77 = *on
c EXSR srBMAST
c Select
c When Status=1215
c* Attempt to open twice
c Eval Msg = 'Attempt made to open a file twice
c + ' Problem corrected.'
c Msg Dsply
c* More such WHEN statements ...
c*
c Endsl
c Endif
C '----------' Dsply
c* Perform Mandatory READ
c Read BM 55
c* Do some database
c* processing here...
c*
C Close pfBMAST
C Eval *inlr=*on
C Return
C
C srBMAST Begsr
C 'IsOpen ?' Dsply
c IsOpn Dsply
c 'Is EOF ?' Dsply
c IsEOF Dsply
c 'Status :' Dsply
c Status Dsply
c 'Op code :' Dsply
c opCode Dsply
c 'Message :' Dsply
c MsgNbr dsply
c ENDSR

OUTPUT :

DSPLY OPEN NOW...


DSPLY IsOpen ?
DSPLY 1
DSPLY Is EOF ?
DSPLY 0

176
RPG-ILE LABS

DSPLY Status :
DSPLY 1215
DSPLY Op code :
DSPLY OPEN F
DSPLY Message :
DSPLY
DSPLY Attempt made to open a file twice. Problem corrected.

LAB : Error handling a READ Statement : EXCLUSIVE LOCK ( *EXCL)

SAM3 locks the PFBMAST for exclusive access. SAM2 tries to open it in Update mode.
Attempt fails : STATUS code is 1271 : Attempt to access a locked object.

SAM3 runs the following program in his own login :-

Program Name : CLLOCK


Type : CLP
The OPM program locks and opens the PFBMAST in exclusive mode.
It then waits with a SNDPGMMSG indefinitely. In the mean time SAM2 runs the RPFIDS2
program (RPGLE) which tries to open PFBMAST in Update Mode. Attempt fails and is
handled by indicator in the LOW section. The error type is clear in the STATUS
variable which contains value 1217 ie attempt to access Locked object.

SAM3’s program :

PGM
/* LOCK THE PFBMAST FILE TOTALLY. LET NO ONE OPEN */
OVRDBF FILE(PFBMAST) RCDFMTLCK((BM *EXCL)) +
OVRSCOPE(*JOB)
OPNDBF FILE(SAM2/PFBMAST) OPTION(*ALL) OPNSCOPE(*JOB)
/* WAIT TILL USER PRESSES ENTER KEY */
SNDPGMMSG MSG('record locked') TOPGMQ(*EXT)
CLOF OPNID(PFBMAST)
DLTOVR FILE(PFBMAST) LVL(*JOB)
ENDPGM

SAM2’s Program :

FPFBMAST UF E DISK USROPN infds(dsBMast)


DMsg s 50a
d*
DDsBMast DS
DIsEOF 10 10
DStatus 11 15 0
DOpCode 16 21
DMsgNbr 46 52
c*
c* ------------------------------------------
C 'OPEN NOW...' DSPLY
C Open pfBMAST 77
C If *IN77
C 'CANNOT OPEN' DSPLY
c status dsply
C Eval *inlr = *on
C Return
c Endif
c Read BM 55
c* Do some database
c* processing here...
c*

177
RPG-ILE LABS

C Close pfBMAST
C Eval *inlr=*on
C Return

OUTPUT :

DSPLY OPEN NOW...


DSPLY CANNOT OPEN
DSPLY 1217

LAB : ERror handling a READ Statement : *SHRRD


Shared for READ (*SHRRD) lock is when one user locks the pf so that he can read it.
But others can only read and update it.

SAM3 locks PFBMAST as *SHRRD. SAM2 tries to open the file in the mean tim ein update
mode. This is what happens : SAM2 opens it successfully !

SAM3’s program :
PGM
/* LOCK THE PFBMAST FILE TOTALLY. LET NO ONE OPEN */
OVRDBF FILE(PFBMAST) RCDFMTLCK((BM *SHRRD)) +
OVRSCOPE(*JOB)
OPNDBF FILE(SAM2/PFBMAST) OPTION(*ALL) OPNSCOPE(*JOB)
/* WAIT TILL USER PRESSES ENTER KEY */
SNDPGMMSG MSG('SHARE READ ') TOPGMQ(*EXT)
CLOF OPNID(PFBMAST)
DLTOVR FILE(PFBMAST) LVL(*JOB)

ENDPGM

SAM2 ‘s program :

FPFBMAST UF E DISK USROPN infds(dsBMast)


DMsg s 50a
d*
DDsBMast DS
DIsEOF 10 10
DStatus 11 15 0
DOpCode 16 21
DMsgNbr 46 52
c*
c* ------------------------------------------
C 'OPEN NOW...' DSPLY
C Open pfBMAST 77
C If *IN77
C 'CANNOT OPEN' DSPLY
c status dsply
C Eval *inlr = *on
C Return
c Endif
c Read BM 55
c* Do some database
c* processing here...
c*
C Close pfBMAST
C Eval *inlr=*on
C Return

178
RPG-ILE LABS

LAB : ERror handling a READ Statement : *SHRUPD


Share update (*SHRUPD) lock is when one user locks the pf so that he can update and
read it. But others can read and update it.

SAM3 locks the file first. SAM2 can access the file in *UPDATE mode.

LAB : Handling READ errors for SHRNUP locks.

SAM3 locks PF with *SHRNUP : SAM2 tries to open file in UPDATE Mode.

SAM2 gets the following response :

OUTPUT :
DSPLY OPEN NOW...
DSPLY CANNOT OPEN
DSPLY 1217

What if SAM2 tries to open the PFBMAST in INPUT mode ?


The file is opened successfully.

LAB : Handling error in EXCLRD (EXCLUSIVE ALLOW read) lock

Sam3 locks the PFBMAST in *EXCLRD.Sam3 tries to open in update mode :

Result :

SAM2 cannot open pf in UPDATE mode.

DSPLY OPEN NOW...


DSPLY CANNOT OPEN
DSPLY 1217

SAM2 successfully opens the file in INPUT mode

Lab : Normal record locks.


SAM3 overrides pfbmast so that when it is opened, it gets a record format lock (as
done prevoisly) as *EXCL.
With sam3’s program running, call rpfids2 for sam2. This program cannot open pf in
update mode.
SAM2 cannot open this file in INPUT mode either.

Code of sam3 :

CLlock :

PGM
/* LOCK THE PFBMAST FILE TOTALLY. LET NO ONE OPEN */
OVRDBF FILE(PFBMAST) RCDFMTLCK((BM *EXCL )) +
OVRSCOPE(*JOB)
/* CALL RPFIDS3 WHICH READS PFBMAST IN UPDATE MODE*/
CALL RPFIDS3
DLTOVR FILE(PFBMAST) LVL(*JOB)
ENDPGM

RPFIDS3 (sam3’s program)

FPFBMAST uF E DISK USROPN infds(dsBMast)


DMsg s 50a

179
RPG-ILE LABS

d*
DDsBMast DS
DIsEOF 10 10
DStatus 11 15 0
DOpCode 16 21
DMsgNbr 46 52
c*
c* ------------------------------------------
C 'OPEN NOW...' DSPLY
C Open pfBMAST 77
C If *IN77
C 'CANNOT OPEN' DSPLY
c status dsply
C Eval *inlr = *on
C Return
c Endif
c Read BM 55
c* Do some database
c* processing here...
c 'ENDING' DSPLY
C Close pfBMAST
C Eval *inlr=*on
C Return

SAM2’s program :

FPFBMAST iF E DISK USROPN infds(dsBMast)


DMsg s 50a
d*
DDsBMast DS
DIsEOF 10 10
DStatus 11 15 0
DOpCode 16 21
DMsgNbr 46 52
c*
c* ------------------------------------------
C 'OPEN NOW...' DSPLY
C Open pfBMAST 77
C If *IN77
C 'CANNOT OPEN' DSPLY
c status dsply
C Eval *inlr = *on
C Return
c Endif
c Read BM 55
c* Do some database
c* processing here...
c 'ENDING 2' DSPLY
C Close pfBMAST
C Eval *inlr=*on
C Return

Sam3’s screen :

DSPLY OPEN NOW...


DSPLY ENDING

180
RPG-ILE LABS

Sam2’s screen : (for both modes : READ FOR Update as well as READ FOR Input)

DSPLY OPEN NOW...


DSPLY CANNOT OPEN
DSPLY 1217

Lab : Effect of File locking in the same job

In the same job, at the same level, a program can open a Exclusively locked file :

PGM
/* LOCK THE PFBMAST FILE TOTALLY. LET NO ONE OPEN */
OVRDBF FILE(PFBMAST) RCDFMTLCK((BM *EXCL)) +
OVRSCOPE(*JOB) SHARE(*NO)
OPNDBF FILE(SAM2/PFBMAST) OPTION(*INP) OPNID(I4) +
OPNSCOPE(*JOB)
/* CALL RPFIDS3 WHICH READS PFBMAST IN UPDATE MODE*/
CALL RPFIDS3
CLOF OPNID(I4)
DLTOVR FILE(PFBMAST) LVL(*JOB)

Here RPFIDS3 has successfully opened the pf in Update mode.

ENDPGM

LAB : Locking excl in sam3a activation group and then opening a file in update mode
in sam3b act grp is possible

Listing of CLLOCK compiled to run in the SAM3A activation group :

PGM
/* LOCK THE PFBMAST FILE TOTALLY. LET NO ONE OPEN */
OVRDBF FILE(PFBMAST) RCDFMTLCK((BM *EXCL)) +
SECURE(*YES) OVRSCOPE(*ACTGRPDFN) SHARE(*NO)
OPNDBF FILE(SAM2/PFBMAST) OPTION(*INP) OPNID(I4) +
OPNSCOPE(*ACTGRPDFN)
/* CALL RPFIDS3 WHICH READS PFBMAST IN UPDATE MODE*/
CALL RPFIDS3
CLOF OPNID(I4)
DLTOVR FILE(PFBMAST) LVL(*ACTGRPDFN)

ENDPGM

Results of DSPJOB : 2 different data paths generated for PFBMAST :


PFBMAST SAM2 PFBMAST *ACTGRPDFN 0000033071 SAM3A
PFBMAST SAM2 PFBMAST *ACTGRPDFN 0000033110 SAM3B

RPFIDS3 is compiled to run in the SAM3B activation group.

LAB : Handling normal record locking

A program tries to read for update, if the READ fails, displays the error (satus
code)

If RPGFIDS3 is started first, it opens the PFBMAST in update mode. A READ operation
is performed. This is READ FOR UPDATE since the open mode was UPDATE.

Now that a READ for UPDATE has bnen done,the record is locked.

181
RPG-ILE LABS

At this time of RPFIDS2 is started, it may open the file in Update mode (since we
have not enabled any object level locking, the database file is for anyone to use and
open in any mode as desired) The RPFIDS2 has no problems opening thie file, but when
it tries to read this fie (READ FOR UPDATE) it cannot because the first record is
already locked by RPFIDS3.
Had RPFIDS2 tried to read the second or any other record (apart from rec 1) it would
have succeeded. The first record is locked by RPFIDS3.
The lock is released only when RPFIDS3 does an explicit UNLOCK operation or reads
another record for update.

Output from RPFIDS2

DSPLY OPEN NOW...


DSPLY CANNOT read
DSPLY 1218

RPFIDS2 opened the file in update mode but could not read record #1. It waited 60
secs (record wait time) and then switched on the indicator in the LO section.

We check state of this indicator and display the STATUS value which comes out to be
1218 !

Code for RPFIDS2 :

FPFBMAST uF E DISK USROPN infds(dsBMast)


DMsg s 50a
d*
DDsBMast DS
DIsEOF 10 10
DStatus 11 15 0
DOpCode 16 21
DMsgNbr 46 52
c*
c* ------------------------------------------
C 'OPEN NOW...' DSPLY
C Open pfBMAST 77
C If *IN77
C 'CANNOT OPEN' DSPLY
c status dsply
C Eval *inlr = *on
C Return
c Endif
c Eval *in55 = '1'
c dow *in55 = '1'
c Read BM 6655
C If *IN66
C 'CANNOT read' DSPLY
c status dsply
c else
c* Do some database
c* processing here...
c 'RPFIDS 2' dsply
c bcode dsply
c bname dsply
c bprice dsply
c endif
c enddo
c 'ENDING 2' DSPLY
c

182
RPG-ILE LABS

C Close pfBMAST
C Eval *inlr=*on
C Return

Code for RPFIDS3 :

FPFBMAST uF E DISK USROPN infds(dsBMast)


DMsg s 50a
d*
DDsBMast DS
DIsEOF 10 10
DStatus 11 15 0
DOpCode 16 21
DMsgNbr 46 52
c*
c* ------------------------------------------
C 'OPEN NOW...' DSPLY
C Open pfBMAST 77
C If *IN77
C 'CANNOT OPEN' DSPLY
c status dsply
C Eval *inlr = *on
C Return
c Endif
c Read BM 55
c* Do some database
c* processing here...
c bcode dsply
c bname dsply
c bprice dsply
c 'ENDING' DSPLY
C Close pfBMAST
C Eval *inlr=*on
C Return

RPFIDS2 will have no problems opening the file in Input mode.In the input mode the
READ opcode causes a READ FOR INQUIRY that does not lock a record.

LAB : Handling READ of UPDATE failures

Program RPFIDS2 tries to perform a READ for Update for 3 times, if all 3 attempts
fail, it does a read for inquiry and display data in the record.

When RPFIDS2 is doing all this, RPFIDS3 has already locked the first record of the
PFBMAST with a READ for UPDATE.

Code for RPFIDS3 remains the same : opens PFMAST in Update mode and reads the first
record as READ for UPDATE. Then it stops with something displaed using DSPLY.

Code for RPFIDS2 :

FPFBMAST uF E DISK USROPN infds(dsBMast)


DMsg s 50a
d*
DDsBMast DS
DIsEOF 10 10
DStatus 11 15 0

183
RPG-ILE LABS

DOpCode 16 21
DMsgNbr 46 52
c*
c* ------------------------------------------
C 'OPEN NOW...' DSPLY
C Open pfBMAST 77
C If *IN77
C 'CANNOT OPEN' DSPLY
c status dsply
C Eval *inlr = *on
c Return
c Endif
c Eval *in66 = '1'
c* This loop goes on till atleast 1 successful
c* READ operation is done.
c*
c dow *in66 = '1'
c Read BM 6655
c* will wait 60 seconds
c* If record still not available
c* will switch on 66
c*
C If *IN66
C 'CANNOT read' DSPLY
c status dsply
c Iter
c else
c* Do some database
c* processing here...
c 'RPFIDS 2' dsply
c bcode dsply
c bname dsply
c bprice dsply
c endif
c enddo
c 'ENDING 2' DSPLY
c
C Close pfBMAST
C Eval *inlr=*on
C Return

OUTPUT of RPFIDS2:

DSPLY OPEN NOW...


DSPLY CANNOT read
DSPLY 1218

LAB : Locking PF with ALLOC

SAM3 runs following program :

PGM
/* LOCK THE PFBMAST FILE TOTALLY. LET NO ONE OPEN */
ALCOBJ OBJ((SAM2/PFBMAST *FILE *EXCL *FIRST)) WAIT(5)
SNDPGMMSG MSG('Object is Alocated *EXCL.') TOPGMQ(*EXT)
DLCOBJ OBJ((SAM2/PFBMAST *FILE *EXCL PFBMAST))
ENDPGM

184
RPG-ILE LABS

SAM2 runs the following program shortly after SAm3 ran his program :

FPFBMAST uF E DISK USROPN infds(dsBMast)


DMsg s 50a
d*
DDsBMast DS
DIsEOF 10 10
DStatus 11 15 0
DOpCode 16 21
DMsgNbr 46 52
c*
c* ------------------------------------------
C 'OPEN NOW...' DSPLY
C Open pfBMAST 77
C If *IN77
C 'CANNOT OPEN' DSPLY
c status dsply
C Eval *inlr = *on
c Return
c Endif
c Eval *in66 = '1'
c* This loop goes on till atleast 1 successful
c* READ operation is done.
c*
c dow *in66 = '1'
c Read BM 6655
c* will wait 60 seconds
c* If record still not available
c* will switch on 66
c*
C If *IN66
C 'CANNOT read' DSPLY
c status dsply
c Iter
c else
c* Do some database
c* processing here...
c 'RPFIDS 2' dsply
c bcode dsply
c bname dsply
c bprice dsply
c endif
c enddo
c 'ENDING 2' DSPLY
c
C Close pfBMAST
C Eval *inlr=*on
C Return

OUTPUT as recd by SAM3 :

Object is Alocated *EXCL.

This msg is displayed till ENTER is pressed.

OUTPUT as seen by SAM2 :

DSPLY OPEN NOW...


DSPLY CANNOT OPEN
DSPLY 1217

185
RPG-ILE LABS

ALCOBJ can be used for all Modes : *EXCL, *SHRRD, *SHRUP, *SHRNUP.

LAB : Error Handling a DELETE operation

Program of SAM3 : RPFIDS3

Opens pfbmast in Update mode and reads first record and stops with a DSPLY. Thus the
first record is effectively locked.

Program of SAM2 : RPFIDS2

FPFBMAST uF E DISK USROPN infds(dsBMast)


DMsg s 50a
d*
DDsBMast DS
DIsEOF 10 10
DStatus 11 15 0
DOpCode 16 21
DMsgNbr 46 52
c*
C 'OPEN NOW...' DSPLY
C Open pfBMAST
c Read BM 55
c Read BM 55
c 1 Setll BM
c 'Will DLT now'Dsply
c* ------------------------------------------------------------
c* ------------------------------------------------------------
c*| Run RPFIDS3 now. RPFIDS3 reads the First rec and locks it.
c*| Can RPFIDS2 delete this record now ?
c* ------------------------------------------------------------
c
c Delete bm 88
c If *in88 = *on
c Eval *in88 = *off
c 'Canot delete'Dsply
c Status Dsply
c Else
c 'dlt done !' Dsply
c Endif
c 'ENDING 2' DSPLY
c
C Close pfBMAST
C Eval *inlr=*on
C Return

OUTPUT :

DSPLY OPEN NOW...


DSPLY Will DLT now
DSPLY Canot delete
DSPLY 1221

Run RPFIDS2 first. When it displays “Will DLT now”, run RPFIDS3. RPFIDS3 reads first
record in the PFBMAST and shows bcode value.Keep RPFIDS3 just at this point and press

186
RPG-ILE LABS

enter to continue running RPFIDS2. Now RPFIDS2 tries to DELETE record #1 but cannot
since RPFIDS3 has locked it. This the 77 indicator of the DELETE opcode becomes ON.
Display the Value of Status which comes out to be 1221 (unable to DELETE !)

NOW try the same trick with UPDATE :

Code for SAM2 is changed as follows :

FPFBMAST uF E DISK USROPN infds(dsBMast)


DMsg s 50a
d*
DDsBMast DS
DIsEOF 10 10
DStatus 11 15 0
DOpCode 16 21
DMsgNbr 46 52
c*
C 'OPEN NOW...' DSPLY
C Open pfBMAST
c Read BM 55
c Read BM 55
c 1 Setll BM
c 'Will UPD now'Dsply
c* ------------------------------------------------------------
c*| Run RPFIDS3 now. RPFIDS3 reads the First rec and locks it.
c*| Can RPFIDS2 delete this record now ?
c* ------------------------------------------------------------
c Eval Bcode = 122
c Eval BName = 'ACAD'
c Eval BPrice= 180
c Update bm 88
c If *in88 = *on
c Eval *in88 = *off
c 'Canot Update'Dsply
c Status Dsply
c Else
c 'UPD done !' Dsply
c Endif
c 'ENDING 2' DSPLY
c
C Close pfBMAST
C Eval *inlr=*on
C Return

OUTPUT :

DSPLY OPEN NOW...


DSPLY Will UPD now
DSPLY Canot Update
DSPLY 1221

Importance of POST opcode :

The fields from position 1 to position 66 in the file feedback section of


the INFDS are always provided and updated even if INFDS is not specified
in the program. The fields from position 67 to position 80 of the file
feedback section of the INFDS are only updated after a POST operation to a
specific device.

LAB : Handling database WRITE errors

187
RPG-ILE LABS

Unique (Primary key) violation :

Following program tries to load duplicate record. BCODE has a Primarky Key constraint
and hence the WRITE operation fails. The status code is displayed.

COUTION : The BKMAST2 file must be Journaled before the following program can run.

Listing :

FpfBMAST2 UF A E DISK InfDS(DSBMAST)


dDSBMAST DS
dStatus *status
f*
c
c Open pfBMAST2 77
c If *in77
c status Dsply
c Eval *inlr = *on
c Return
c EndIF
c
c Read BM 55
c* -------------------------------------------------
c Eval Bcode = 101
c Eval BName = 'xxx'
c Eval BPrice = 100
c*
c* WRITE operation will fails.
c* Hence use indicator in LO indicator.
c*
c Write BM 77
c If *in77 = *on
c* error inwrite
c 'cannot write'Dsply
c Status Dsply
c Eval *in77 = *off
c Endif
c
c
c Close pfBMAST2
c Eval *inlr = *on
c Return

Record cannot be written since 1 record already has this BCODE value.
STATUS CODE : 1215

Referential Intregity Constraint Violation :

LAB :Handling referential integrity errors.

Pre-Requisites : 2 Physical files : 1 master database and 1 Transaction database must


be available. Th Master database file (PFBMAST) contains BCODE,BNAME and BPRICE.
Another database file BTRANS contains BCODE, BQTY,BMODE. The BCODE in Master file PK
constraint and bcode in transaction file has FK constraint. The followign program
tries to write invalid record to the Transaction file. The status code is displayed.
(1022)

188
RPG-ILE LABS

F*fBMAST2 IF E DISK
FpfTRANs UF A E DISK Prefix(x:1) INFDS(dstrans) USROPN
dDSTRANS DS
dStatus *status
f*
f* PfTran has fields with the same name as in PFBMAST.
f* If you use prefix for pfTRAN, all fields and record format also
f* can be referenced by replaceing their first letter by x. For
f* example, a field in BTrans is BCode.It becomes xCode.
f*
c
c Open PFTRANS
c
c Read BTrans 55
c* put a invalid value for xcode. there is no book inthe Book Master
c* table with this name. Since the 2 tables are linked by referential
c* Integrity, the record cannot be written to BTrans
c* -------------------------------------------------
c Eval xcode = 7777
c Eval xQty= 7777
c Eval xMode = 'I'
c*
c* WRITE operation will fails.
c* Hence use indicator in LO indicator.
c*
c Write BTrans 77
c If *in77 = *on
c* error inwrite
c 'cannot write'Dsply
c Status Dsply
c Eval *in77 = *off
c Endif
c
c
c Close PFTRANS
c Eval *inlr = *on
c Return

OUTPUT :

DSPLY cannot write


DSPLY 1022

LAB : Inserting NULL values into database fields

Database file :

A UNIQUE(*EXCNULL)
A R BM
A BCODE 4S 0 ALWNULL
A BNAME 30A
A BPRICE 7S 2
A K BCODE

UNIQUE(*EXCNUL) allows duplicate NULL values. UNIQUE constraint is not applied to


NULL values entered.

189
RPG-ILE LABS

By saying ALWNUL to BCODE, we can enter NULL values into BCODE.

Program Write 1 Null to BCODE and XML to BNAME. Then it reads all records form start
and disdplays records where BCODe is NULL.

Listing :

FpfBMAST UF A E DISK InfDS(DSBMAST) UsrOpn


DDSBMAST DS
DStatus *status
D*
c
c Open pfBMAST 77
c If *in77
c status Dsply
c Eval *inlr = *on
c Return
c EndIF
c
c Read BM 55
c* ---Set Bcode to NULL using NULL Indicator ---------
c Eval %NullInd(bcode) = '1'
c Eval BName = 'XML'
c Eval BPrice = 177
c*
c Write BM 77
c If *in77 = *on
c* error inwrite
c 'cannot write'Dsply
c Status Dsply
c Eval *in77 = *off
c Endif
c
c 1 Setll BM
c Dow '1'
c Read Bm 77
c If *in77
c Leave
c Endif
c If %NullInd(BCode)
c 'Null !' Dsply
c BName Dsply
c EndIf
c Enddo
c Close pfBMAST
c Eval *inlr = *on
c Return

Compilation : 14 then F4 specify *USRCTL to Allow Null Fields option.Pree ENTER.

c If %NullInd(BCode)

This line checks if Value of BCOde for currently read record is Null or Not. If it IS
null, the %NULLIND function returns a TRUE.

OUTPUT :

190
RPG-ILE LABS

DSPLY Null !
DSPLY name1
DSPLY Null !
DSPLY name1
DSPLY Null !
DSPLY XML
DSPLY Null !
DSPLY XML

During compilation you get following errors /warnings if *USRCTL is not specified for
BCODE :

Msg id Sv Number Seq Message text


*RNF7150 00 1 000100 Record BM in file PFBMAST contains null capable fie
*RNF7420 30 19 001500 %NULLIND cannot be used when ALWNULL(*USRCTL) is no
specified.
*RNF7420 30 37 003300 %NULLIND cannot be used when ALWNULL(*USRCTL) is no
specified.

OUTPUT of RUNQRY on PFBMAST :


BCODE BNAME
BPRICE
- Hee 120.00
- XML 177.00
- XML 177.00
- XML 177.00

191
RPG-ILE LABS

Flat Physical file

Use CRTPF to create a flat physical file. Don’t specify the source PF or member name.
Only specify the record format length, and press ENTER.

RPG listing to access the flat physical file :

fpfflat if e disk rename(pfflat:r1) prefix(x)


c Read r1
c xpfflat dsply
c Eval *inlr = *on

192
RPG-ILE LABS

LAB : Overriding a member of Database file

fPFMEM IF E DISK usropn


dQCMDEXC PR ExtPgm('QCMDEXC')
darg1 50a
darg2 15p 5
dcmd001 s 50a
dcmdLen s 15p 5
c Open pfmem
c Read bm 44
c bcode dsply
c bname dsply
c Close PFMEM
c*
c Eval cmd001 = 'OVRDBF file(PFMEM) MBR(JAN)'
c eval cmdLen = %Len(%trim(cmd001))
c callp QCMDEXC(cmd001:cmdlen)
c Open PFMEM
c 1 Setll bm
C Read BM 6655
c 66'read err' dsply
c BCode Dsply
c BName Dsply
c close pfmem
c*
c Eval cmd001 = 'dltovr file(PFMEM)'
c eval cmdLen = %Len(%trim(cmd001))
c callp QCMDEXC(cmd001:cmdlen)
c Eval cmd001 = 'OVRDBF file(PFMEM) MBR(FEB)'
c eval cmdLen = %Len(%trim(cmd001))
c callp QCMDEXC(cmd001:cmdlen)
c Open PFMEM
C Read BM 55
c BCode Dsply
c BName Dsply
c Close PFMEM
c Eval *inlr = *on
c Return

The Physical file PFMEM has 3 members : PFMEM , JAN and FEB

The data in JN and FEB can be displayed using above program.

ODP

193
RPG-ILE LABS

ENBEDDED SQL :
LAB : Embedded SQL : basics

dnCode s 4s 0 inz(0)
dnTemp s 7s 2 inz(45.00)
d
d
d* I have made sure that only 1 record is returned.
d*
d*
c/EXEC SQL
c+ Select bcode into :nCode from pfbmast where
c+ bprice = :nTemp
c/END-EXEC
c nCode Dsply
c Eval *inlr = *on
c Return
c*
c*

NOTES :

1. Type of the program should be SQLRPGLE.


1. Do option 14 and press F4. Specify *NONE to commitment control.

LAB : Implement a Cursor

dnCode s 4s 0 inz(0)
dsName s 10a
dnTemp s 7s 2 inz(45.00)
d
d
c/EXEC SQL
c+ DECLARE C1 Cursor For select bcode,bname from pfbmast
c+ where bcode IS NULL
c/END-EXEC
c/EXEC SQL
c+ Open C1
c/END-EXEC
c
c* Start reading the data
c* ----------------------
c Dow '1'
c/EXEC SQL
c+ Fetch from C1 into :nCode,:sName
c/END-EXEC
c*-
c If SQLCOD = 100
c Leave
c Endif
c*--
c
c nCode Dsply
c sName Dsply
c Enddo
c
c* -------Now close the cursor ----------

194
RPG-ILE LABS

c/EXEC SQL
c+ Close C1
c/END-EXEC
c Eval *inlr = *on
c Return
c*
c*

LAB : Implementing a Scroll cursor

Accept the relative position from the current cursor pointer position and display the
record. If too high a relative position is specified, the SQLCOD is set to 100
(position exceeeds the last record in the cursor) The pointer remains at the current
record.

Relative works this way : Suppose of cursor pointer position is rec #4. If you
specify RELATIVE :n where n is 2, the pointer goes like : 5,6 and stops at 6 since
that is the second record from the 4th record. IF you specify Relative :n where nis –
2, the pointer goes back 2 records ie. To the second record.

Listing :

dnCode s 4s 0 inz(0)
dsName s 10a
dnRecNum s 4s 0 inz(-2)
d
d
c/EXEC SQL
c+ DECLARE C1 scroll Cursor For select bcode,bname from pfbmast
c+ where bcode <110
c/END-EXEC
c/EXEC SQL
c+ Open C1
c/END-EXEC
c
c* Start reading the data
c* ----------------------
c Dow '1'
c/EXEC SQL
c+ Fetch relative :nRecNum from C1 into :nCode,:sName
c/END-EXEC
c*--
c
c nCode Dsply
c sName Dsply
c SqlCod Dsply
c SqlWrn Dsply
c 'Pos :(0:End)'Dsply nRecNum
c If nRecNum = 0
c Leave
c Endif
c
c Enddo
c
c* -------Now close the cursor ----------
c/EXEC SQL
c+ Close C1
c/END-EXEC
c Eval *inlr = *on

195
RPG-ILE LABS

c Return
c*
c*

OUTPUT :

DSPLY 108
DSPLY EXCEL
DSPLY 100
DSPLY
DSPLY Pos :(0:End) 2
1
DSPLY 108
DSPLY EXCEL
DSPLY 100
DSPLY
DSPLY Pos :(0:End) 1

Type reply, press Enter.


Reply . . . __________________________________

LAB : Implementing a Dynamic scroll cursor

Program displays the first record in the cursor (which contains all records). It asks
for position and sets pointer to that position. Actually, it asks if the current
record is to be updateed or not before positioning to the requested record. After
updating , it points to the new record requested.

dnCode s 4s 0 inz(0)
dsName s 10a
dnRecNum s 4s 0 inz(1)
dsDecide s 1a inz('n')
d
d
c/EXEC SQL
c+ DECLARE C1 DYNAMIC scroll Cursor For select bcode,bname
c+ from pfbmast
c/END-EXEC
c/EXEC SQL
c+ Open C1
c/END-EXEC
c
c* Start reading the data
c* ----------------------
c Dow '1'
c/EXEC SQL
c+ Fetch relative :nRecNum from C1 into :nCode,:sName
c/END-EXEC
c*--
c 'DATA READ :-'Dsply
c nCode Dsply
c sName Dsply
c 'Code/Warn :' Dsply
c SqlCod Dsply
c SqlWrn Dsply

196
RPG-ILE LABS

c 'Pos :(9:End)'Dsply nRecNum


c If nRecNum = 9
c Leave
c Endif
c
c
c 'Update ?' dsply sDecide
c*002
c If sDecide = 'y' Or sDecide = 'Y'
c 'New Code :' dsply nCode
c
c/exec sql
c+ update pfbmast set BCode =:nCode Where Current of C1
c/End-Exec
c 'UPD CD/WRN :'Dsply
c SqlCod Dsply
c Sqlwrn Dsply
c Sqlwn0 Dsply
c EndIf
c*002
c Enddo
c
c* -------Now close the cursor ----------
c/EXEC SQL
c+ Close C1
c/END-EXEC
c Eval *inlr = *on
c Return
c*
c*

Output :

LAB : Error Handling : watching values of SQLCOD and SQLERR for insert/update errors

In the following program, the first iteration of the DOW loop tries to load 120value
into to the BCODE field. This violates PK constraint on the BKMAST since oen of the
records already has BCODE as 120. Study the values of SQLCOD and SQLERR :

dnCode s 4s 0 inz(120)
dsName s 10a
dnPrice s 7s 2 inz(100)
dsDecide s 1a inz('n')
dnTemp s 7s 2 inz(45.00)
dCntr s 4s 0 inz(0)
d* ----------------------------------------------------------------------
D* SQL Communications area :automatically added,hence I commented it out.
d* ----------------------------------------------------------------------
D*SQLCA DS
D* SQLAID 1 8A
D* SQLABC 9 12B 0
D* SQLCOD 13 16B 0
D* SQLERL 17 18B 0
D* SQLERM 19 88A

197
RPG-ILE LABS

D* SQLERP 89 96A
D* SQLERRD 97 120B 0 DIM(6)
D* SQLERR 97 120A
D* SQLER1 97 100B 0
D* SQLER2 101 104B 0
D* SQLER3 105 108B 0
D* SQLER4 109 112B 0
D* SQLER5 113 116B 0
D* SQLER6 117 120B 0
D* SQLWRN 121 131A
D* SQLWN0 121 121A
D* SQLWN1 122 122A
D* SQLWN2 123 123A
D* SQLWN3 124 124A
D* SQLWN4 125 125A
D* SQLWN5 126 126A
D* SQLWN6 127 127A
D* SQLWN7 128 128A
D* SQLWN8 129 129A
D* SQLWN9 130 130A
D* SQLWNA 131 131A
D* SQLSTT 132 136A
c
c
c Dow '1'
c/EXEC SQL
c+ Insert into pfbmast values (:nCode,:sName,:nPrice)
c/END-EXEC
c*-
c 'Code :' Dsply
c nCode Dsply
c 'Price :' dsply
c nPrice Dsply
c 'sqlcod' Dsply
c sqlcod Dsply
c*--
c 'sqlerr' Dsply
c sqlerr Dsply
c*--
c 'sqlwrn' Dsply
c sqlwrn Dsply
c*--
c 'sqlwn0' Dsply
c sqlwn0 Dsply
c*--
c Eval nPrice = nPrice * 2
c Eval nCode = nCode - 1
c 'Exit ?' Dsply sDecide
c If sDecide = 'y' OR sDecide = 'Y'
Leave
c Endif
c Enddo
c
c Eval *inlr = *on
c Return
c*
c*

OUTPUT : For error in input :

198
RPG-ILE LABS

DSPLY Code :
DSPLY 120
DSPLY Price :
DSPLY 10000  This is actually 100.00
DSPLY sqlcod
DSPLY 803-
DSPLY sqlerr
DSPLY 50345009
DSPLY sqlwrn
DSPLY
DSPLY sqlwn0
DSPLY
DSPLY Exit ? n

Type reply, press Enter.


Reply . . . ________________________________________

SQLCOD is –803 when the PK constraint in violated.

OUTPUT : For valid input :

DSPLY Code :
DSPLY 119
DSPLY Price :
DSPLY 20000
DSPLY sqlcod
DSPLY 0
DSPLY sqlerr
DSPLY 7956
DSPLY sqlwrn
DSPLY
DSPLY sqlwn0
DSPLY
DSPLY Exit ? n

Type reply, press Enter.


Reply . . . ________________________________________

LAB : Prepared statement

199
RPG-ILE LABS

LAB : QCMDEXC

dStrCommand s 7a inz('WRKSPLF')
dCmdLen s 15p 5 inz(7)
c call 'QCMDEXC'
c Parm StrCommand
c Parm CmdLen
c 'Done' dsply
c Eval *inlr = *on
c Return

Interactive Comand Execution by promting :

d* Program demostrates command prompting. The program will run


d* CrtLIb command and display the command on screen, since
d* ? is used, prompting for the entire command starts.
d* Provide a lib name, type and press ENTER.
d* If you press F3, (refuse to run the command) a message is
d* recieved. Use PSSR to handle error.
d*
dStrCommand s 90a
dCmdLen s 15p 5 inz(7)
c Eval StrCommand = '?CRTLIB'
c call 'QCMDEXC'
c Parm StrCommand
c Parm CmdLen
c End1 Tag
c 'Done' dsply
c Eval *inlr = *on
c Return
c *PSSR Begsr
c Goto End1
c Endsr

200
RPG-ILE LABS

PAGE : 253
ADDITIONS TO THE MAIN COVERAGE BEGIN HERE (ADDILE5 )
LAB : Work in VARSIZE (passign a pramater lesser than expected size as a prameter to procedure)

201
RPG-ILE LABS

LAB :
/free
DateDue = %date (DUEDATE: *ISO);
DaysLate = %diff (CurDate: DateDue: *d);

LAB : %Char %Int

Convert a char to int , int to char, char to float float to char

LAB :

D CharToNum PI 30P 9
D string 100A CONST VARYING
D decComma 2A CONST OPTIONS(*NOPASS)
D currency 1A CONST OPTIONS(*NOPASS)

/free
// override defaults if optional parameters were passed
if %parms > 1;
decPoint = %subst(decComma : 1 : 1);
comma = %subst(decComma : 2 :1);
endif;
if %parms > 2;
cursym = currency;
endif;
// initialization
len = %len(string);
// begin reading the integer part
pNumPart = %addr(intPart);
// loop through characters
for i = 1 to len;
c = %subst(string : i : 1);
select;
// ignore blanks, digit separator, currency symbol
when c = comma or c = *blank or c = cursym;
iter;
// decimal point: switch to reading the decimal part
when c = decPoint;
pNumPart = %addr(decPart);
iter;
// sign: remember the most recent sign
when c = '+' or c = '-';
sign = c;
iter;
// more signs: cr, CR, () are all negative signs
when c = 'C' or c = 'R' or
c = 'c' or c = 'r' or
c = '(' or c = ')';
sign = '-';
iter;
// a digit: add it to the current build area
other;
eval numPart = numPart + c;
endsl;
endfor;
// copy the digit strings into the correct positions in the
// zoned variable, using the character overlay

202
RPG-ILE LABS

decStart = %len(result) - %decPos(result) + 1;


intStart = decStart - %len(intPart);
eval %subst(resChars : intStart : %len(intPart)) = intPart;
eval %subst(resChars : decStart : %len(decPart)) = decPart;
// if the sign is negative, return a negative value
if sign = '-';
return -result;
// otherwise, return the positive value
else;
return result;
endif;
/end-free
pe

LAB :

Example of a recursive call to a sub-procedure


(A data item that is defined
in a subprocedure uses automatic storage unless the STATIC keyword is
specified for the definition.)

LAB : Embeded SQL code in ILE program to be convered to Module and Bound to main line module
using : CRTPGM and CGTBNGRPG (see page 80 of ilerpg)

LAB : working with compiler reports

You can control the spacing and pagination of the compiler listing through the use
of the /EJECT and /SPACE compiler directives. The /EJECT directive forces a
page break. The /SPACE directive controls line spacing within the listing. For more
information on these directives refer to the ILE RPG Reference.

LAB : RPG cycle program with Match fields

LAB : A status Module that contains error data structure. Any module / procedure hasa problem, it
updates the data structure. This is useful when a second procedure wishes to see the resultts of
execution of the last procedure.

Module is a NOMAIN and has only error data structure.

LAB : Running 2 programs in same actgrp and in commitment env. If 1 commits, can the other
rollback ?

LAB : Running 2 programs in same actgrp and in commitment env. If 1 program reads a rec, can
some other job access the record ? (is it locked ? )

How is locking done in commitment control ?

LAB : Demonstrate power of UPDSRVPGM : by independantly updating a single module in a service


program and running the client application without any re-compilation.

LAB : 2 Modules export procedure of the same name, it that OK ? If a client calls the procedure,
which one will be called ?

203
RPG-ILE LABS

LAB : A main line program declares a global int i. A bound module exports an int i. The main line
module get which I ? the imported one or the local one ?

LAB : Debugging a LE program that uses /COPY to include external source code fragments

LAB : using CHGPGM, UPDPGM, DSPPGM,DSPPGMREF,WRKPGM


In general, you can update a program by replacing modules as needed. For
example, if you add a new procedure to a module, you recompile the module
object, and then update the program. You do not have to re-create the program.
UPDPGM can be used to update Module objects.
To update a program created by CRTBNDRPG command, you must ensure that the
revised module is in the library QTEMP. This is because the temporary module
used when the CRTBNDRPG command was issued, was created in QTEMP. Once
the module is in QTEMP, you can issue the UPDPGM command to replace the
module.

To change the
optimization level of a program, use the CHGPGM command.

DSPMOD : displays the optimisation level of the Module.

LAB : observability

Removing Observability
Observability involves the kinds of data that can be stored with an object, and that
allow the object to be changed without recompiling the source. The addition of this
data increases the size of the object. Consequently, you may want to remove the
data in order to reduce object size. But once the data is removed, observability is
also removed. You must recompile the source and recreate the program to replace
the data. The types of data are:
Create Data Represented by the *CRTDTA value. This data is necessary to
translate the code to machine instructions. The object must have
this data before you can change the optimization level.
Debug Data Represented by the *DBGDTA value. This data is necessary to
allow an object to be debugged.
Profiling Data Represented by the *BLKORD and *PRCORD values. This data is
necessary to allow the system to re-apply block order and
procedure order profiling data.

Use the CHGPGM command or the CHGMOD command to remove some or all
the data from a program or module respectively. Removing all observability
reduces an object to its minimum size (without compression). It is not possible to
change the object in any way unless you re-create it. Therefore, ensure that you
86 ILE RPG Programmer’s Guide
have all source required to create the program or have a comparable program
object with CRTDATA. To re-create it, you must have authorization to access the
source code.
Reducing an Object’s Size
The create data (*CRTDTA) associated with an ILE program or module may make
up more than half of the object’s size. By removing or compressing this data, you
will reduce the secondary storage requirements for your programs significantly.
Changing a Module or Program

Page 105

204
RPG-ILE LABS

LAB : DSPSRVPGM : To display procedures (services) exported by the service procedure.

LAB : working with service program

Changing A Service Program


You can update or change a service program in the same ways available to a
program object. In other words, you can:
v Update the service program (using UPDSRVPGM)
v Change the optimization level (using CHGSRVPGM)
v Remove observability (using CHGSRVPGM)
v Reduce the size (using CPROBJ)
For more information on any of the above points, see “Changing a Module or
Program” on page 84.
Related CL commands
The following CL commands are also used with service programs:
v Change Service Program (CHGSRVPGM)
v Display Service Program (DSPSRVPGM)
v Delete Service Program (DLTSRVPGM)
v Update Service Program (UPDSRVPGM)
v Work with Service Program (WRKSRVPGM)

LAB : using operation descriptors

The service program makes use of operational descriptors, which is an ILE


construct used when the precise nature of a passed parameter is not known ahead
of time, in this case the length. The operational descriptors are created on a call to
a procedure when you specify the operation extender (D) on the CALLB operation,
or when OPDESC is specified on the prototype.
To use the operational descriptors, the service program must call the ILE bindable
API, CEEDOD (Retrieve Operational Descriptor). This API requires certain
parameters which must be defined for the CALLB operation. However, it is the last
parameter which provides the information needed, namely, the length. For more
information on operational descriptors, see “Using Operational Descriptors” on
page 135.

*=================================================================*
* CvtToHex - convert input string to hex output string
*=================================================================*
H COPYRIGHT('(C) Copyright MyCompany 1995')
D/COPY RPGGUIDE/QRPGLE,CVTHEXPR
*-----------------------------------------------------------------*
* Main entry parameters
* 1. Input: string character(n)
* 2. Output: hex string character(2 * n)
*-----------------------------------------------------------------*
D CvtToHex PI OPDESC
D InString 16383 CONST OPTIONS(*VARSIZE)
D HexString 32766 OPTIONS(*VARSIZE)
*-----------------------------------------------------------------*
* Prototype for CEEDOD (Retrieve operational descriptor)
*-----------------------------------------------------------------*
D CEEDOD PR
D ParmNum 10I 0 CONST
D 10I 0
D 10I 0
D 10I 0
D 10I 0
D 10I 0
D 12A OPTIONS(*OMIT)
* Parameters passed to CEEDOD
D DescType S 10I 0

205
RPG-ILE LABS

D DataType S 10I 0
D DescInfo1 S 10I 0
D DescInfo2 S 10I 0
D InLen S 10I 0
D HexLen S 10I 0
*-----------------------------------------------------------------*
* Other fields used by the program *
*-----------------------------------------------------------------*
D HexDigits C CONST('0123456789ABCDEF')
D IntDs DS
D IntNum 5I 0 INZ(0)
D IntChar 1 OVERLAY(IntNum:2)
D HexDs DS
D HexC1 1
D HexC2 1
D InChar S 1
D Pos S 5P 0
D HexPos S 5P 0
Figure 42. Source for Service Program CvtToHex (Part 1 of 2)
Chapter 8. Creating a Service Program 93
*-----------------------------------------------------------------*
* Use the operational descriptors to determine the lengths of *
* the parameters that were passed. *
*-----------------------------------------------------------------*
C CALLP CEEDOD(1 : DescType : DataType :
C DescInfo1 : DescInfo2: Inlen :
C *OMIT)
C CALLP CEEDOD(2 : DescType : DataType :
C DescInfo1 : DescInfo2: HexLen :
C *OMIT)
*-----------------------------------------------------------------*
* Determine the length to handle (minimum of the input length *
* and half of the hex length) *
*-----------------------------------------------------------------*
C IFInLen > HexLen / 2
C EVAL InLen = HexLen / 2
C ENDIF
*-----------------------------------------------------------------*
* For each character in the input string, convert to a 2-byte *
* hexadecimal representation (for example, '5' --> 'F5') *
*-----------------------------------------------------------------*
C EVAL HexPos = 1
C DO InLen Pos
C EVAL InChar = %SUBST(InString : Pos :1)
C EXSR GetHex
C EVAL %SUBST(HexString : HexPos : 2) = HexDs
C EVAL HexPos = HexPos + 2
C ENDDO
*-----------------------------------------------------------------*
* Done; return to caller. *
*-----------------------------------------------------------------*
C RETURN
*=================================================================*
* GetHex - subroutine to convert 'InChar' to 'HexDs' *
**
* Use division by 16 to separate the two hexadecimal digits. *
* The quotient is the first digit, the remainder is the second. *
*=================================================================*
C GetHex BEGSR
C EVAL IntChar = InChar
C IntNum DIV 16 X1 5 0
C MVR X2 5 0
*-----------------------------------------------------------------*
* Use the hexadecimal digit (plus 1) to substring the list of *
* hexadecimal characters '012...CDEF'. *
*-----------------------------------------------------------------*

206
RPG-ILE LABS

C EVAL HexC1 = %SUBST(HexDigits:X1+1:1)


C EVAL HexC2 = %SUBST(HexDigits:X2+1:1)
C ENDSR
Figure 42. Source for Service Program CvtToHex (Part 2 of 2)
Sample Service Program
94 ILE RPG Programmer’s Guide
When designing this service program, it was decided to make use of binder
language to determine the interface, so that the program could be more easily
updated at a later date. Figure 44 shows the binder language needed to define the
exports of the service program CVTTOHEX. This source is used in the EXPORT,
SRCFILE and SRCMBR parameters of the CRTSRVPGM command.
The parameter SIGNATURE on STRPGMEXP identifies the interface that the
service program will provide. In this case, the export identified in the binder
language is the interface. Any program bound to CVTTOHEX will make use of this
signature.
The binder language EXPORT statements identify the exports of the service
program. You need one for each procedure whose exports you want to make
available to the caller. In this case, the service program contains one module which
contains one procedure. Hence, only one EXPORT statement is required.
*=================================================================*
* CvtToHex - convert input string to hex output string
*
* Parameters
* 1. Input: string character(n)
* 2. Output: hex string character(2 * n)
*=================================================================*
D CvtToHex PR OPDESC
D InString 16383 CONST OPTIONS(*VARSIZE)
D HexString 32766 OPTIONS(*VARSIZE)
Figure 43. Source for /COPY Member with Prototype for CvtToHex
STRPGMEXP SIGNATURE('CVTHEX')
EXPORT SYMBOL('CVTTOHEX')
ENDPGMEXP
Figure 44. Source for Binder Language for CvtToHex
Sample Service Program

LAB : system reply list

Use the Change Job (CHGJOB) command (or other CL job command) to indicate
that your job uses the reply list for inquiry messages. To do this, you should
specify *SYSRPYL for the Inquiry Message Reply (INQMSGRPY) attribute.
The reply list is only used when an inquiry message is sent by a job that has the
Inquiry Message Reply (INQMSGRPY) attribute specified as
INQMSGRPY(*SYSRPYL). The INQMSGRPY parameter occurs on the following CL
commands:
v Change Job (CHGJOB)
v Change Job Description (CHGJOBD)
v Create Job Description (CRTJOBD)
v Submit Job (SBMJOB).
You can also use the Work with Reply List Entry (WRKRPYLE) command to
change or remove entries in the system reply list. For details of the ADDRPYLE
and WRKRPYLE commands, see the CL and APIs section of

LAB : Run a program in DFTACTGRP or a named ACTGRP , do not seton the LR


Are the files opened ? does RCLRSC close the files.

207
RPG-ILE LABS

Isthis why a parent program uses FREE opcode ? to free the resources of a child that ended
normally without setting On the LR ?

When a program does not do a seton lr and ends, and suppose it runs in a named act grp, then the
files opened by the program remain open. Do RCLRSC (mostly) to close files or do a RCLACTGRP to
delete the act grp : this cleans up any resources loced up and closes open files.

LAB : Parent handles the *ESCAPE message sent by the child.

d
LAB : RCLRSC

Reclaim Resources Command


The Reclaim Resources (RCLRSC) command is designed to free the resources for
programs that are no longer active. The command works differently depending on
how the program was created. If the program is an OPM program or was created
with DFTACTGRP(*YES), then the RCLRSC command will close open files and free
static storage.
For ILE programs or service programs that were activated into the OPM default
activation group because they were created with *CALLER, files will be closed
when the RCLRSC command is issued. For programs, the storage will be
re-initialized; however, the storage will not be released. For service programs, the
storage will neither be re-initialized nor released.

For ILE programs associated with a named activation group, the RCLRSC
command has no effect. You must use the RCLACTGRP command to free resources
in a named activation group.

LAB :

Creating a Program for Source Debugging


In this example you create the program EMPRPT so that you can debug it using
the source debugger. The DBGVIEW parameter on either CRTBNDRPG or
CRTRPGMOD determines what type of debug data is created during compilation.
The parameter provides six options which allow you to select which view(s) you
want:
v *STMT — allows you to display variables and set breakpoints at statement
locations using a compiler listing. No source is displayed with this view.
v *SOURCE — creates a view identical to your input source.
v *COPY — creates a source view and a view containing the source of any /COPY
members.
v *LIST — creates a view similar to the compiler listing.
v *ALL — creates all of the above views.
v *NONE — no debug data is created.
The source for EMPRPT is shown in Figure 28 on page 56.

208
RPG-ILE LABS

1. To create the object type:


CRTBNDRPG PGM(MYLIB/EMPRPT) DBGVIEW(*SOURCE) DFTACTGRP(*NO)

209
RPG-ILE LABS

Chapter 12 : debugging programs

LAB : Debugging a ILE program


Prepare your ILE RPG program for debugging
• Start a debug session
• Add and remove programs from a debug session
• View the program source from a debug session
• Set and remove breakpoints and watch conditions
• Step through a program
• Display and change the value of fields
• Display the attributes of fields
• Equate a shorthand name to a field, expression, or debug command

You can prevent database files in production libraries from being modified
unintentionally by using one of the following commands:
v Use the Start Debug (STRDBG) command and retain the default *NO for the
UPDPROD parameter

LAB :

LAB :

LAB :

LAB :

LAB :

LAB :

LAB :

LAB :

LAB :

LAB :

LAB :

LAB :

210
RPG-ILE LABS

LAB :

LAB :

LAB :

LAB :

LAB :

LAB :

LAB :

LAB :

LAB :

LAB :

LAB :

LAB :

LAB : Compiler listing as a very useful source of documentation (esp for program
maintenance).
Specify debugging and line no options in the compiler commandoptions toinclude all
them in the compiler listing.

SEE PAGE 89

LAB : Debugging : All options of debugging views etc. to get most out of debugger.

Debug commands.

Lab : page 89
Both the CRTBNDRPG and CRTRPGMOD (see “Using the CRTRPGMOD
Command” on page 74) commands create and update a data area with the status of
the last compilation. This data area is named RETURNCODE, is 400 characters
long, and is placed into library QTEMP.

SECTION 3 : SHARING ODP,OVERRIDE, OPENDBF ,ACTIVATION GROUP

LAB : STUDY OF SHARED OPEN DATA PATH AND SCOPING.

211
RPG-ILE LABS

LISTING OF CL001 :

CALL RP01
CALL RP02

OUTPUT :

1
2
1
2

RP01 AND RP02 READ 2 RECORDS FROM FILE PFBM2. 9TYPICAL BCODE,BNAME BPRICE FILE)

OUTPUT SHOWS BCODES AS 1 2 1 2. THIS IS BECAUSE WHEN RP01 IS STARTED, IT OPENS THE
FILE PFBM2 AND SETS UP AN ODP. Reads 2 records and thus displays 1 2. RP01 ends and
closes the ODP. RP02 starts and sets up a new ODP. It does the same thing : reads 2
records and displays bcode : thus output is 1 2.

See the following listing of the CL001 program :

PGM
OVRDBF FILE(PFBM2) SECURE(*NO) OVRSCOPE(*CALLLVL) +
SHARE(*YES)
OPNDBF FILE(SAM2/PFBM2) OPTION(*ALL) OPNSCOPE(*ACTGRP)
SNDPGMMSG MSG('OUTPUT WHEN THE OVERRIDE WAS APPLIED ') +
TOPGMQ(*EXT)
CALL RP01
CALL RP02
CLOF OPNID(PFBM2)
DLTOVR FILE(PFBM2) LVL(*)
SNDPGMMSG MSG('______OVERRIDE REMOVE_______ ') +
TOPGMQ(*EXT)
CALL RP01
CALL RP02
ENDPGM

OUTPUT :

The ovrdbf specifies that file PFBM2 will be opened in the SHARE mode and that this
override is scoped to the CALL LEVEL. The currnet CL001 program sets up a call level.
All RPG programs called from this CL001 will run in that call level.

Scope of the the SHARE (*YES) is ACTGRPDFN level. Since all the programs will run in
the DEFAULT ACTIVATION group (they are RPG/400 programs) the ODP is shared by call
applications from this and higher call levels.

Thus RP01 RP02 and RP003 will share the ODP setup by the OPNDBF command.
Listing of RP01 :

FPFBM2 IF E DISK
C 'RP01' DSPLY
C READ BM 33
C BCODE DSPLY
C READ BM 33
C BCODE DSPLY
C CALL 'RP003'
C SETON LR

212
RPG-ILE LABS

Listing of RP003 :

FPFBM2 IF E DISK
C 'RP003' DSPLY
C READ BM 33
C BCODE DSPLY
C READ BM 33
C BCODE DSPLY
C SETON LR

Listing of RP02 :

FPFBM2 IF E DISK
C 'RP02' DSPLY
C READ BM 33
C BCODE DSPLY
C READ BM 33
C BCODE DSPLY
C SETON LR

RP01 calls RP003 which is run at a higher scoping level.


RP003 continues to use the shared ODP since the shared ODP is scoped to ACTGRPDFN.

Lab : CL001 calls the programs RP01,RP02 and RP01 calls RP003. CL001 also calls CL002
which sinply calls RP05 and RP06. CL002 does not say anything about override which
CL001 has setup an override at the activation group level.
Will override apply to the cl002 program ? all are running in the same activation
group.
YES

CL002 calls Rp05 and rp06 and shows that ODP is shared.

Listing of CL001 :-

PGM
OVRDBF FILE(PFBM2) SECURE(*NO) OVRSCOPE(*CALLLVL) +
SHARE(*YES)
OPNDBF FILE(SAM2/PFBM2) OPTION(*ALL) OPNSCOPE(*ACTGRP)
SNDPGMMSG MSG('OUTPUT WHEN THE OVERRIDE WAS APPLIED ') +
TOPGMQ(*EXT)
CALL RP01
CALL CL002
CALL RP02
CLOF OPNID(PFBM2)
DLTOVR FILE(PFBM2) LVL(*)
SNDPGMMSG MSG('______OVERRIDE REMOVE_______ ') +
TOPGMQ(*EXT)
CALL RP01
CALL RP02
ENDPGM

CL002 listing :

PGM
SNDPGMMSG MSG('CHILD CL002 PROGRAM STARTED. ') +
TOPGMQ(*EXT)
CALL RP01
CALL RP02
SNDPGMMSG MSG('______CL002 DONE_______ ') +
TOPGMQ(*EXT)

213
RPG-ILE LABS

ENDPGM

LAB : Override a OVERRIDE which was applied at the prevous call level.

Cl002 LISTING :

PGM
SNDPGMMSG MSG('CHILD CL002 PROGRAM STARTED.NO SHARING') +
TOPGMQ(*EXT)
OVRDBF FILE(PFBM2) SHARE(*NO) OPNSCOPE(*ACTGRPDFN)
CALL RP01
CALL RP02
SNDPGMMSG MSG('______CL002 DONE_______ ') +
TOPGMQ(*EXT)
DLTOVR FILE(PFBM2)
ENDPGM

CL002’S OVRDBF HAS NOT WORKED. THE FILE SHARE MODE STILL REMAINS *YES/

THEREFORE, RP01 AND RP02 (CALLED IN CL002) SHOWED THE RECORDS 56 AND 78 RATHER THAN 1
2 1 2 AS EXPECTED.

MAYBE CL002 WILL HAVE TO RUN IN ANOTHER ACTIVATION GROUP IN ODER TO GET A SEPARATE
ODP. SINCE CL002 IS A CHILD OF CL001 WHICH ALREADY IMPLEMENTED AN OVERRIDE SCOPED TO
THE ACTGRPLEVEL, CL002 COMES AT A HIGHER LEVEL AND BELONGS TO THE SAME ACTIVATION
GROUP AND IS THUS INFLUENCED BY THE PARENTS OVERRIDE SETTING.

LAB : GETTING A SEPARATE ODP FOR CHILD PROGRAM CL002.

HOW TO GET A SEPARATE ODP FOR CL002 WHICH IS A CHILD OF CL001 ?

HERE HOW …

LISTING OF CL002 :

PGM
SNDPGMMSG MSG('CHILD CL002 PROGRAM STARTED.NO SHARING') +
TOPGMQ(*EXT)
OVRDBF FILE(PFBM2) SECURE(*YES) SHARE(*NO) +
OPNSCOPE(*ACTGRPDFN)
CALL RP01
CALL RP02
SNDPGMMSG MSG('______CL002 DONE_______ ') +
TOPGMQ(*EXT)
DLTOVR FILE(PFBM2)
ENDPGM

MAKE SURE SECURE OPTION IS SET TO YES. THIS SECURES THE OVERRIDE FROM OTHER
OVERRIDES.

FINAL LISTING OF ALL THE FILES : CL001,CL002,RP01,RP02,RP003 IS AS UNDER :

CL001 :
PGM
OVRDBF FILE(PFBM2) SECURE(*NO) OVRSCOPE(*CALLLVL) +
SHARE(*YES)
OPNDBF FILE(SAM2/PFBM2) OPTION(*ALL) OPNSCOPE(*ACTGRP)
SNDPGMMSG MSG('OUTPUT WHEN THE OVERRIDE WAS APPLIED ') +
TOPGMQ(*EXT)
CALL RP01

214
RPG-ILE LABS

CALL CL002
CALL RP02
CLOF OPNID(PFBM2)
DLTOVR FILE(PFBM2) LVL(*)
SNDPGMMSG MSG('______OVERRIDE REMOVE_______ ') +
TOPGMQ(*EXT)
CALL RP01
CALL RP02
ENDPGM

CL002 :

PGM
SNDPGMMSG MSG('CHILD CL002 PROGRAM STARTED.NO SHARING') +
TOPGMQ(*EXT)
OVRDBF FILE(PFBM2) SECURE(*YES) SHARE(*NO) +
OPNSCOPE(*ACTGRPDFN)
CALL RP01
CALL RP02
SNDPGMMSG MSG('______CL002 DONE_______ ') +
TOPGMQ(*EXT)
DLTOVR FILE(PFBM2)
ENDPGM

RP01 :
FPFBM2 IF E DISK
C 'RP01' DSPLY
C READ BM 33
C BCODE DSPLY
C READ BM 33
C BCODE DSPLY
C CALL 'RP003'
C SETON LR

RP003 :

FPFBM2 IF E DISK
C 'RP003' DSPLY
C READ BM 33
C BCODE DSPLY
C READ BM 33
C BCODE DSPLY
C SETON LR

RP02 :
FPFBM2 IF E DISK
C 'RP02' DSPLY
C READ BM 33
C BCODE DSPLY
C READ BM 33
C BCODE DSPLY
C SETON LR

OUTPUT :

OUTPUT WHEN THE OVERRIDE WAS APPLIED


DSPLY RP01
DSPLY 1
DSPLY 2

215
RPG-ILE LABS

DSPLY RP003
DSPLY 3
DSPLY 4
CHILD CL002 PROGRAM STARTED.NO SHARING
DSPLY RP01
DSPLY 1
DSPLY 2
DSPLY RP003
DSPLY 1
DSPLY 2
DSPLY RP02
DSPLY 1
DSPLY 2
______CL002 DONE_______
DSPLY RP02
DSPLY 5
DSPLY 6
______OVERRIDE REMOVE_______
DSPLY RP01
DSPLY 1
DSPLY 2
DSPLY RP003
DSPLY 1
DSPLY 2
DSPLY RP02
DSPLY 1
DSPLY 2

SCOPING : I HAD TO KEEP THE SCOPING AS *CALLLVL FOR OVRDBF AND *ACTGRP FOR SHARE=YES
DOES THIS MEAN THAT OVRDBF WILL BE EFFECTIVE FOR THE CURRENT CL001 PROGRAM (CALLLVL)
? THEN WHY IS THERE ONE MORE OPTION FOR SCOPING FOR SHARE OPTION ? HOW COME SHARE
OPTION HAS NO CALLLVL SCOPING ? WHY ARE WE FORCED TO SPECIFY *ACTGRPDFN OR *JOB FOR
SHARE = *YES OPTION ?

LAB : OPNQRY FILE

CLQRYST CALLS CLQRY WHICH USES OPNQRYF AND CALLS RP001. THE ODP IS SHARED
SO THAT RP001 DOES NOT GET ALL RECORDS OF PF001,ONLY RECORDS WHERE BCODE < 4.

THIS IS A MOST COMMONLY USED TECHNIQUE.

LISTING OF CLQRYST :

PGM
DCL &S *CHAR 40 'BCODE < 4'
CALL CLQRY PARM(&S)
ENDPGM

LISTING OF CLQRYF :
PGM PARM(&QRYSTR)
DCL &QRYSTR *CHAR 40
OVRDBF FILE(PFBM2) SHARE(*YES) OPNSCOPE(*ACTGRPDFN)
OPNQRYF FILE((SAM2/PFBM2)) OPTION(*ALL) QRYSLT(&QRYSTR)
/* SHOW ALL RECORDS */
CALL RP001
CLOF PFBM2
DLTOVR FILE(PFBM2)
ENDPGM

216
RPG-ILE LABS

LISTING OF RP001 :

FPFBM2 IF E DISK
C SETOF 03
C *IN03 DOWEQ*OFF
C READ BM 03
C BCODE DSPLY
C ENDDO
C*
C SETON LR

OUTPUT :

1
2
3

Heirarchy :

JOB 
Contains ACTIVATION GROUP
Has CALL LEVELS

217
RPG-ILE LABS

LAB : External indicator (The job switch)

Linkage : RPIND in samlesrc.

CODE :

* RPIND.
* Demostrates external indicators.
* First set U1 to *ON. then do WRKJOB to see the job atributes.
* See the job Switch. Notice that it becomes 1000 0000
* The first '1' corresponds to U1 indicator.
*
*
c Eval *inU1 = *on
c If *inU1 = *ON
c 'test' Dsply
c Endif
c Eval *inlr = *on

PF contents :

nil

OUTPUT :

The job switch changes to 1000 0000 since U1 is turned ON.

REMARKS :
U1,…U8 are called external indicators since other CL /RPG programs can access the
state oof those indicators.

LAB : Time opcode

dT1 s T
c time T1
c T1 dsply
c Eval *inlr = *on

LAB : Display a block on the screen / Working with Hex characters.

DCon2             C                   Const(X'10')
c     Con2          dsply                         
c                   Eval      *inlr = *on         
c                   Return                        
c*

LAB : RT indicator as against LR indicator.

218
RPG-ILE LABS

CODE :

* RPIND1.
* Demostrates RT indicator.
* set up an impossible condition for the LR indicator.
* In the following code, LR is never turned ON.
* So program never properly terminates.
*
* But after executing the last C instruction, the program
* returns control to OS and seems to end.This is since RT is 1
* If RT is not 1, program will loop infinetely or till LR
* becomes 1.
* The program actually does not end since calling it agains
* displays value of 'a' incremented by 1.
*
da s 5i 0 inz(10)
c Eval *inRT = *on
c 'a = ' dsply
c a dsply
c Eval a = a + 1
c*
c* set up an impossible condition
c*
c if a <0
c Eval *inlr = *on
c Endif

PF contents :

nil

OUTPUT :

Since LR is never turned on, program does not terminate but displays increasing
values of a every time it is called.

REMARKS :

Setting RT to ON allows program to return control to OS without ending.

LAB : The DEFINE option in the CRTBNDRPG command.

Linkage : RPDEFUN

CODE :

c 'Starting...' DSPLY
/if defined(myvar1)
c 'ya ! defined'Dsply
/else
c 'Nop!' Dsply
/endif
c Eval *inlr=*on

PF contents :

219
RPG-ILE LABS

nil

OUTPUT :

REMARKS :

Compile the RPDEFUN program with option 14. and run the program. Output is NOP !
since the MYVAR1 varaible is not defined. Now type 14 to compile the same program
again and press F4 and F10 for extended prompting.

In the DEFINE parameter specify the name MYVAR1 to #define this variable.Press Enter
to Compile . Run the program now. Output is is Ya! Defined. Since now myvar1 is
defined to the program.

This is called conditional compilation.

220
RPG-ILE LABS

LAB : Random number generation (one possible way).

Linkage : RPRANDOM

CODE :

dVar1 s 6s 0
dVar2 s 6s 0
dSysTime s z
c do 3
c time SysTime
c* SysTime Dsply
c Extrct SysTime:*ms Var1
c Eval Var1 = Var1/10000
c Var1 Dsply
c Extrct SysTime:*s Var2
c Eval Var1 = %abs(Var1 - Var2)
c Var1 Dsply
c EndDo
c Eval *inlr = *on

Random numbers will be generated between 0 and 99.

12.52.00.993000  99 will be generated

12.52.00.000000  0 will be generated

Number
generated
2005 03 24 12.52.53.613000 |53-61| = 8
2005 03 24 12.52.54.865000 32
2005 03 24 12.52.56.514000 5
2005 03 24 12.53.38.244000 14
2005 03 24 12.53.39.537000 14
2005 03 24 12.53.41.114000 30
2005 03 24 12.54.53.157000 38
2005 03 24 12.54.55.002000 55
2005 03 24 12.54.57.313000 26
2005 03 24 12.56.45.359000 10
2005 03 24 12.56.46.807000 34
2005 03 24 12.56.48.153000 33

Alternative approach : Pick up the MS (milli sec) part, at any time, it will be
random between 000 to 999.

PF contents :

OUTPUT :

REMARKS :

221
RPG-ILE LABS

LAB : Test cases

Concept : A nomain module contains a FNTEST procedure that accepts 3 arguments. The
arguments are lenghts of sides of a triangle. If the lenghts are same, the triangle
is a equilateral triangle. In that case, a 3 is returned. If any 2 sides have equal
length, a 2 is returned (isosceles triangle). If none of the sides are equal, a 0 is
returned.

We design a test program to test the procedure against some test data which we hard
coded into the test program.
Name of the stub program : RPTEST.

It is bound with the RPTEST1 to form JSRP1 *PGM object.

Before running JSRP1, use CHGJOB to modify the SWITCH of your job to
1000 000. This makes U1 ON. RPTEST will produce output only if U1 is ON.

Linkage : RPTEST (stub program to test FNTEST proc in RPTEST1 module) RPTEST1 (no
main contains FNTEST procedure)
Both RPTEST and RPTEST1 are Bound by copy to form JSRP1 program object.
Run JSRP1 to start the test.

CODE :

RPTEST Listing : This is the PEP module.

dFNTest PR 5i 0
d 5i 0 value
d 5i 0 value
d 5i 0 value
d*****
dRetVal s 5i 0 inz(0)
dSide1 s 5i 0 inz(10)
dSide2 s 5i 0 inz(10)
dSide3 s 5i 0 inz(10)
c*
c* Test Case #1.
c* Check for EQUILATERAL TRIANGLE.
c*
c U1'EQUILA :3' Dsply
c Eval RetVal = FNTest(Side1:Side2:Side3)
c U1RetVal Dsply
c*
c* Test Case #2.
c* Check for ISOSCELES TRIANGLE.
c*
c Eval Side1 = 5
c Eval RetVal = FNTest(Side1:Side2:Side3)
c U1'ISOSCE : 2' Dsply
c U1RetVal Dsply
c*
c* Test Case #3.
c* Check for other than ISO and EQUI.
c*
c Eval Side2 = 4
c Eval RetVal = FNTest(Side1:Side2:Side3)
c U1'None :0' Dsply
c U1RetVal Dsply
c Eval *inlr = *on

222
RPG-ILE LABS

RPTEST1 Listing : This is the nomain module.

H*
HNomain
H* FNTEST return values
H* 3 : Equilateral triangle
H* 2 : Isosceles triangle
H* 0 : None of the above
H*
H*
dFNTEST PR 5i 0
d 5i 0 value
d 5i 0 value
d 5i 0 value
pFNTEST B export
dFNTEST PI 5i 0
dsd1 5i 0 value
dsd2 5i 0 value
dsd3 5i 0 value
dRetVal s 5i 0 inz(-2)
c*
c if (sd1=sd2) and (sd1=sd3) and (sd2=sd3)
c Eval Retval = 3
c return RetVal
c EndIf
c*
c if (sd1 = sd2 ) or (sd1 = sd3) or ( sd2 = sd
c Eval Retval = 2
c return RetVal
c* isosceles triangle
c EndIf
c*
c if (sd1 <>sd2 ) or (sd1 <>sd3) or ( sd2 <>sd
c Eval Retval = 0
c return RetVal
c* isosceles triangle
c EndIf
c*
c
PFNTEST E

PF contents :

nil

OUTPUT :

3 sets of test data produce 3 expected results. We are not testing for invalid data
(either numeric or otherwise).

REMARKS :

Other testing areas such as Boundary level testing, validation testing are not
covered in this Lab.

LAB : Test case. Program crash because of data overflow.

Program tries to calculate take home amount using formula for compound interest.

223
RPG-ILE LABS

Linkage : RPOFL

CODE :

dth s 5i 0 inz(0)
droi s 5i 0 inz(10000)
damt s 5i 0 inz(10000)
dyrs s 5i 0 inz(50)
c Eval th = amt * (1 + roi/100) ** yrs
c th dsply
c Eval *inlr=*on

PF contents :

nil

OUTPUT :

The target for a numeric operation is too small to hold the result (C G D F)

Message . . . . : Application error. MCH1212 unmonitored by RPDELME at


statement 0000000005, instruction X'0000'.

Cause . . . . . : The application ended abnormally because an exception


occurred and was not handled. The name of the program to which the
unhandled exception is sent is RPDELME RPDELME RPDELME. The program was
stopped at the high-level language statement number(s) 0000000005 at the
time the message was sent. If more than one statement number is shown, the
program is an optimized ILE program. Optimization does not allow a single
statement number to be determined. If *N is shown as a value, it means the real
value was not available.

REMARKS :

Program is not robust enough to handle overflow errors. EVAL needs to do Error
handling.

Better solution :

The programmer who wrote the procedure should generate Tech specifications of the
procedure and design the procedure to accept argument values only within certain
sensible ranges.
The procedure should set retval variables to some negative values to indicate invalid
data values.
The tech specs can be handed over to the testor who will build the test cases around
the tech specs.

224
RPG-ILE LABS

LAB : Free and End-Free

Linkage : RPFREE

CODE :

Linkage : RPFREE

ds1 s 4 inz('abc')
dn1 s 4s 0 inz(1)
dn2 s 4s 0 inz(2)
dn3 s 4s 0 inz(3)
d**
/free

eval n3 = n1 + n2;
dsply 'N1 : ' ;
dsply N1 ;
dsply 'N2 : ';
dsply N2;
dsply 'N3 : ';
dsply N3;
eval *inlr = *on;
/End-Free

PF contents :

OUTPUT :

REMARKS :

LAB : Simple program to access records of PFBM.

Linkage : RPDSREAD

Code :

Fdsdbread cf e Workstn
Fpfbm if e Disk
dtemp s 4s 0
/free
Read bm;
Eval DCode = BCode;
Eval DName = BName;
Eval DPrice = BPrice;
Dow *in03 = *off;
Exfmt R1;

if (*in04 = *on);
*in04 = *off;
readp bm;

225
RPG-ILE LABS

if %Eof;
Setll 1, bm;
Read bm;
EndIf;
EndIf ;

if (*in05 = *on);
*in05 = *off;
read bm;
If %Eof;
// setll *hival, bm; DOES NOT WORK !!!
EndIf;
EndIf ;

Eval DCode = BCode;


Eval DName = BName;
Eval DPrice = BPrice;
EndDo;

Eval *inlr = *on;


/End-Free

226
RPG-ILE LABS

227
RPG-ILE LABS

FDsmemori CF E Workstn usropn


D*
D* ___Prototype section begin___
D*
DReverse PR
D 6s 0
DPGenerate PR
DN1 6s 0
DN2 6s 0
DN3 6s 0
DComputeScore Pr
d 6s 0
d 6s 0
d 6s 0
d 3s 0
D* __Prototype section End__
DW0N1 s 6s 0
DW0N2 s 6s 0
DW0N3 s 6s 0
DW0Score s 3s 0
C* Main procedure__
c Dow *IN03 = *OFF
c Eval *in25 = *OFF
c* ____________________________________
c* Dont Show The 'Enter data ' message.
c* ------------------------------------
c Callp PGenerate(W0N1:W0N2:W0N3)
c Eval F1 = W0N1
c Eval F2 = W0N2
c Eval F3 = W0N3
c ExFmt Rmemori
c 03 Eval *inlr = *on
c 03 Return
c Eval F1 = *Zeros
c Eval F2 = *Zeros
c Eval F3 = *Zeros
c Eval *in25 = *on
c* Enter Data___
c ExFmt RMemori
c*
c 03 Eval *inlr = *on
c 03 Return
c Callp ComputeScore (W0N1:W0N2:W0N3:W0Score)
c eval DScore = W0Score
c EndDo
c Eval *inlr = *on
c Return
c*
c* Main Procedure End
c*
c* Sub-Procedure Section Begin
c* Procedure to generate 3 random numbers.
PPGenerate B
DPgenerate PI
DN1 6s 0
DN2 6s 0
DN3 6s 0
DSysTime s z
DTemp s 6s 0
D*

228
RPG-ILE LABS

c Time SysTime
c Extrct SysTime:*ms N1
c Callp Reverse(N1)
c Extrct Systime:*s temp
c Eval temp = temp * 10
c Eval N1 = %Abs(temp-N1)
c Eval F1 = N1
c
C open(e) dsmemori
c If %error()
c* do nothing
c EndIf
c Time SysTime
c Extrct SysTime:*ms N2
c Callp Reverse(N2)
c Extrct Systime:*s temp
c Eval temp = temp * 10
c Eval N2 = %Abs(temp-N2)
c Eval F2 = N2
c*
c*
C close dsmemori
C open dsmemori
c Time SysTime
c Extrct SysTime:*ms N3
c Callp Reverse(N3)
c Extrct Systime:*s temp
c Eval temp = temp * 10
c Eval N3 = %Abs(temp-N3)
c Eval F3 = N3
c*
c*
PPGenerate E
P*
P* Calculates the score
P*
PComputeScore B
dComputeScore PI
dW0N1 6s 0
dW0N2 6s 0
dW0N3 6s 0
dW0Score 3s 0
d*
c If (F1 = W0N1) AND (F2=W0N2) AND (F3=W0N3)
c Eval W0Score = 100
c EndIf
c If (F1 = W0N1) AND (F2=W0N2) and (F3<>W0N3)
c Eval W0Score = 60
c EndIf
c If (F1 = W0N1) and (F2<>W0N2) and (F3<>W0N3)
c Eval W0Score = 30
c EndIf
c If (F1 <>W0N1) and (F2<>W0N2) and (F3<>W0N3)
c Eval W0Score = 0
c EndIf
PComputeScore E
PReverse b
dReverse Pi
dArg1 6s 0
dTemp s 6s 0

229
RPG-ILE LABS

dStr s 6a
dCounter s 3s 0 inz(1)
dCounter1 s 3s 0 inz(6)
dArrStr s 1a Dim(6)
c Eval str = %trim(%char(Arg1))
c Eval temp = %len(str)
c Do 6
c Eval ArrStr(counter) = %subst(str:counter1:1)
c Eval Counter1 = counter1 -1
c Eval Counter = counter +1
c EndDo
c Eval Counter1 = 6
c Eval Counter = 1
c Do 6
c Eval %subst(str:counter:1)=arrStr(Counter)
c Eval Counter = counter +1
c EndDo
c move str Temp
c Eval Arg1 = Temp
PReverse e

230

You might also like