create an ifs handler using rpg open-access · 2020. 2. 12. · the readline procedure is called to...

30
Create an IFS Handler using RPG Open-Access Craig Pelkie [email protected]

Upload: others

Post on 13-Sep-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

Create an IFS Handler using

RPG Open-Access Craig Pelkie [email protected]

Page 2: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

Create an IFS Handler using RPG Open-Access 2012-07-20

Copyright © 2012, Craig Pelkie, ALL RIGHTS RESERVED

Page 3: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

FirThis each

Figur

st pass program is h record.

H option(*s H dftactgrp

Fqcustcdt I Fqsysprt O

/free *inlr

open q

dow 1

re

if en

ex enddo

close

/end-free

Oqsysprt E O O O O O O O O O O O

re 1: This is t

– RPG p the “baseli

rcstmt : *nod(*no)

IF E O F 132

= *on;

qcustcdt;

= 1;

ead qcustcdt

f %eof; leave; ndif;

xcept; ;

qcustcdt;

E

the output of

programne” RPG pro

debugio)

DISK PRINT

;

cusnum lstnam init street city state zipcod cdtlmt chgcod baldue cdtdue

f the IFS01 pr

m IFS01ogram. It sim

usropn ER

1

+2 +2 +2 +2 +2 +2 +2 +2 +2 +2

rogram.

1

1 mply reads from the QCCUSTCDT dataabase file an

nd prints

ifs01

Page 4: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

SecThis file I

Figur

cond pa program usI/O operatio

H option(*s H dftactgrp

Fqcustcdt I F

Fqsysprt O

/free *inlr

open q

dow 1

re

if en

ex enddo

close

/end-free

Oqsysprt E O O O O O O O O O O O

re 2: When th

ass – RPses the HANDon associate

rcstmt : *nod(*no)

IF E

O F 132

= *on;

qcustcdt;

= 1;

ead(e) qcust

f %eof or %e leave; ndif;

xcept; ;

qcustcdt;

E

he program is

PG progrDLER keyword with the f

debugio)

DISK

PRINT

cdt;

rror;

cusnum lstnam init street city state zipcod cdtlmt chgcod baldue cdtdue

s called, it ge

ram IFSrd on the F-file.

usropn handler('

ER

1

+2 +2 +2 +2 +2 +2 +2 +2 +2 +2

ets the MCH3

2

S02 spec. When

PELKIE/IFSHD

3401 error. Th

n run, the ha

DLR')

he handler pr

A

andler progr

rogram has n

ram is called

not been crea

d for each

ifs0ated yet.

2

Page 5: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

SecThis can

Figur

cond pa is the first verify that t

H option(*s H dftactgrp

Fqsysprt O

/copy QOAR/

D QOA D opcode

C *ENTRY C

/free opcode except

if opc ex re endif

if opc ex re endif

if opc ex *i re endif

/end-free

Oqsysprt E O O Oqsysprt E O Oqsysprt E O Oqsysprt E O

re 3: This is t

ass – Haversion of tthe handler

rcstmt : *nod(*no)

O F 132

/QRPGLESRC,Q

ds s

Y PLI PARM

e = QOA.rpgOt exop;

code = QrnOpexcept exopeneturn; ;

code = QrnOpexcept exreadeturn; ;

code = QrnOpexcept excloseinlr = *on; eturn; ;

E E E E

the output of

andler phe handler is working

debugio)

PRINT

RNOPENACC

ST M

peration;

eration_OPEN;

eration_READ;

eration_CLOSe;

exop opcode exopen exread exclose

f the handler

rogramprogram. Itwith each o

ER

likeds(Qr like(QOA.

QOA

;

;

E;

1 +2 1 1 1

program.

A

D

3

IFSHDLts purpose isf the file I/O

nOpenAccess_rpgOperation

A

'QOA.rpgOper

'OPEN called

'READ called

'CLOSE calle

C

LR s to simply O opcodes.

_T) n)

ration'

d'

d'

ed'

B

A — Q

B — Q

C — i

D — Q

“react” whe

QRPNOPENACC

QrnOpenacce

mplicit para

QrnOperatio

en called, so

Page 22

ss_T Page

ameter from

on_x Page 2

o that you

ifs0

27

m caller

23

3

Page 6: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

Figur

Cod

Whe

The

The Becaerro

Whein th

re 4: When th

e notes

en the IFS02

handler pro

READ operatause the calr.

en the callerhe handler.

he program r

program is

ogram is inv

tion handlerler is expec

r ends in err

runs, it gets t

s called, it in

voked when

r does not dcting that th

ror, it implic

the MCH1202

nvokes the h

the OPEN an

o anything, e CUSREC rec

citly invokes

4

2 (Decimal Da

handler prog

nd READ oper

it simply record format

s the CLOSE o

ata Area).

gram IFSHDL

rations run.

eturns from t will have v

operation fo

LR.

the handlervalid values,

or the file, w

r program t the caller e

which is agai

ifs04

o the caller.ends in

in handled

4

.

Page 7: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

5

Third pass – Handler program IFSHDLR.v2 This is the second version of the handler program. It simulates a read operation by returning hard-coded values in the CUSREC record format.

H option(*srcstmt : *nodebugio) H dftactgrp(*no) Fqcustcdt_tIF E DISK template F extdesc('QIWS/QCUSTCDT') Fqsysprt O F 132 PRINTER /copy QOAR/QRPGLESRC,QRNOPENACC D QOA ds likeds(QrnOpenAccess_T) D opcode s like(QOA.rpgOperation) D qcustcdt ds likerec(cusrec) D based(QOA.inputBuffer) D readCalled s n C *ENTRY PLIST C PARM QOA /free opcode = QOA.rpgOperation; except exop; if opcode = QrnOperation_OPEN; except exopen; return; endif; if opcode = QrnOperation_READ; except exread; if readCalled; QOA.eof = *on; return; endif; qcustcdt.cusnum = 123456; qcustcdt.lstnam = 'PELKIE'; qcustcdt.init = 'C R'; qcustcdt.street = '12 OWL'; qcustcdt.city = 'JAMUL'; qcustcdt.state = 'CA'; qcustcdt.zipcod = 92018; qcustcdt.cdtlmt = 1000; qcustcdt.chgcod = 2; qcustcdt.baldue = 12.34; qcustcdt.cdtdue = 56.78; readCalled = *on; return; endif; if opcode = QrnOperation_CLOSE; except exclose; *inlr = *on; return; endif; /end-free Oqsysprt E exop 1 O 'QOA.rpgOperation' O opcode +2 Oqsysprt E exopen 1 O 'OPEN called' Oqsysprt E exread 1 O 'READ called' Oqsysprt E exclose 1 O 'CLOSE called'

A

B

C

D

Page 8: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

Figur

Figur

re 5: This sho

re 6: This is t

ows that the

the output of

READ operat

f running the

tion is called

IFS02 progra

6

twice. On the

am.

e second call,, the EOF ind

dicator is set.

ifs0

ifs0

5

6

Page 9: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

7

Code notes

A — the qcustcdt_t (“template”) is defined. This is used to make the record format definition available to the program, without actually defining the file as an input file within the program.

B — the qcustcdt data structure is defined as being like the CUSREC record format. This implicity defines the data structure as a qualified data structure. The data structure is based on the QOA.inputBuffer pointer.

The QOA.inputBuffer pointer is set in the calling program (IFS02). It points to the input buffer for the QCUSTCDT file that is defined in that program. In other words, the storage for the CUSREC record format is “owned by” program IFS02.

The inputBuffer pointer is defined in the QrnOpenAccess_T data structure (see page 27).

C — the readCalled indicator is set in the first pass through the read operation. On the second read operation, the QOA.eof indicator is set to simulate the end of file (after “reading” the one hard-coded record). See page 28 for the definition of eof.

D — the values for the “record” are moved into the subfields of the qcustcdt data structure. This simulates reading the data from the IFS text file.

Page 10: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

8

RPG module IFSTEXTR4 (Scott Klement) This is the source code for the IFSTEXTR4 RPG module. It is posted on Scott Klement’s web site (www.scottklement.com).

The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on each subsequent call.

** Service program to assist in creating TEXT files in the IFS ** ** To compile: ** CRTRPGMOD IFSTEXTR4 SRCFILE(IFSEBOOK/QRPGLESRC) DBGVIEW(*LIST) ** CRTSRVPGM IFSTEXTR4 TEXT('IFS Text service program') ** EXPORT(*SRCFILE) SRCFILE(IFSEBOOK/QSRVSRC) H NOMAIN OPTION(*NOSHOWCPY: *SRCSTMT) D/copy ifsebook/qrpglesrc,ifsio_h D/copy ifsebook/qrpglesrc,ifstext_h *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * The concept here is very simple: * 1) Write the data passed to us into the stream file. * 2) Add the end of line characters. *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ P writeline B export D writeline PI 10I 0 D fd 10I 0 value D text * value D len 10I 0 value D rc1 S 10I 0 D rc2 S 10I 0 D eol S 2A C* write the text provided c if len > 0 c eval rc1 = write(fd: text: len) c if rc1 < 1 c return rc1 c endif c endif C* then add the end-of-line chars c eval eol = x'0d25' c eval rc2 = write(fd: %addr(eol): 2) c if rc2 < 1 c return rc2 c endif c return rc1 + rc2 P E *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * This one's a bit more complicated. * a) We don't know how long the text will go before * an end-of-line sequence is encountered. * b) We could just read one byte at a time until we found * the EOL sequence, but that would run very slowly * since it's inefficient to transfer chunks of data * that small from disk. * * So... we keep a "read buffer". We load chunks of data * from disk into the buffer, then get one character at a * time from that buffer. *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ P readline B export D readline PI 10I 0 D fd 10I 0 value D text * value D maxlen 10I 0 value D rdbuf S 1024A static D rdpos S 10I 0 static D rdlen S 10I 0 static D p_retstr S * D RetStr S 32766A based(p_retstr) D len S 10I 0

Page 11: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

9

c eval len = 0 c eval p_retstr = text c eval %subst(RetStr:1:MaxLen) = *blanks c dow 1 = 1 C* Load the buffer c if rdpos>=rdlen c eval rdpos = 0 c eval rdlen=read(fd:%addr(rdbuf):%size(rdbuf)) c if rdlen < 1 c return -1 c endif c endif C* Is this the end of the line? c eval rdpos = rdpos + 1 c if %subst(rdbuf:rdpos:1) = x'25' c return len c endif C* Otherwise, add it to the text string. c if %subst(rdbuf:rdpos:1) <> x'0d' c and len<maxlen c eval len = len + 1 c eval %subst(retstr:len:1) = c %subst(rdbuf:rdpos:1) c endif c enddo c return len P E

Page 12: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

10

RPG program IFS03 This program calls the handler that reads from the IFS. The handler is now implemented as a procedure in a service program, rather than as a callable program.

H option(*srcstmt : *nodebugio) H bnddir('IFSHDLR') H dftactgrp(*no) **************************************************************** * Define the file and its handler. **************************************************************** Fqcustcdt IF E DISK usropn F handler(ifsHandler) Fqsysprt O F 132 PRINTER **************************************************************** * The prototype for the ifsHandler procedure. * The QOA parameter is passed to the procedure. **************************************************************** D ifsHandler pr D QOA likeds(QrnOpenAccess_T) /copy QOAR/QRPGLESRC,QRNOPENACC /free *inlr = *on; //********************************************************* // Open the file. If any error on open, print error // message, end program. //********************************************************* open(e) qcustcdt; if %error; except error; return; endif; //********************************************************* // Go into "read loop" to read records from the file. //********************************************************* dow 1 = 1; read(e) qcustcdt; if %eof or %error; leave; endif; except qcust; enddo; //********************************************************* // Close the file. //********************************************************* close qcustcdt; /end-free Oqsysprt E error 1 O 'Error on open' Oqsysprt E qcust 1 O cusnum O lstnam +2 O init +2 O street +2 O city +2 O state +2 O zipcod +2 O cdtlmt +2 O chgcod +2 O baldue +2 O cdtdue +2

A

B

C

D

E

Page 13: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

Cod

A —proc

B —proc

C — foun

D —set i

E —

If yooper

Figur

e notes

the qcustcdcedure.

the prototycedure.

the OPEN opnd or if the u

— the read lon the handl

the CLOSE o

ou use an eration (in th

re 7: This is t

dt file is de

ype for the i

peration is inuser is not a

oop uses theer.

operation is

explicit OPEe handler) c

the QCUSTCD

fined with t

ifsHandler p

nvoked. If tauthorized t

e READ opera

invoked, wh

EN operatiocan release

DT.txt file in I

he handler

procedure is

there is an eo it), the %e

ation, which

hich invokes

on, you sho the resourc

IFS directory

11

keyword. Th

s defined. T

error on the error condit

invokes the

s the handle

ould code ace(s) that w

/rpgoa

his time, the

The QOA para

open (for eion is handl

e handler. T

er.

an explicit were acquire

e handler is

ameter is ex

example, if ted.

The %eof and

CLOSE operad by the OPE

s the ifsHan

xplicitly pass

the text file

d %error con

ation. The EN.

dler

sed to the

is not

nditions are

close

ifs0

7

Page 14: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

12

Handler program IFSHDLR3 This is the handler program that reads from the IFS text file.

H nomain H option(*srcstmt : *nodebugio) H bnddir('QC2LE') H bnddir('IFSEBOOK/IFSTEXT') /copy IFSEBOOK/QRPGLESRC,IFSIO_H /copy IFSEBOOK/QRPGLESRC,IFSTEXT_H /copy QOAR/QRPGLESRC,QRNOPENACC **************************************************************** * Procedure ifsHandler * * This procedure receives control when invoked by RPG-OA * in a client program. The QOA parameter is implicitly * passed. **************************************************************** PifsHandler B export D PI D QOA likeds(QrnOpenAccess_T) **************************************************************** * The QCUSTCDT structure is based on the QOA.inputBuffer * pointer. It is the storage for the record format in * the client program. **************************************************************** D qcustcdt e ds extname('QIWS/QCUSTCDT') D qualified D based(QOA.inputBuffer) **************************************************************** * The opcode is one of the supported file I/O opcodes. **************************************************************** D opcode s like(QOA.rpgOperation) **************************************************************** * These fields are used with the IFS read procedures. * * fd - file descriptor, provides a "handle" to the * IFS file. Coded as static so that it keeps * its value across invocations of the procedure. * readLength - the length of the data returned from the * call to the readline procedure. * textData - the data that is returned as a "record" from * the text file. **************************************************************** D fd s 10i 0 static D readLength s 10i 0 D textData s 68 **************************************************************** * Define RPG status code for errors * (see ILE RPG Reference, "File Exception/Errors") **************************************************************** D ERROR_EXPLICIT_OPEN_CLOSE... D c 01217 /free opcode = QOA.rpgOperation; //********************************************************* // OPEN operation //********************************************************* if opcode = QrnOperation_OPEN; fd = open('/rpgoa/qcustcdt.txt' : O_RDONLY + O_TEXTDATA); if fd < 0; QOA.rpgStatus = ERROR_EXPLICIT_OPEN_CLOSE; endif; return; endif;

A

B

C

D

E

F

Page 15: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

13

//********************************************************* // READ operation //********************************************************* if opcode = QrnOperation_READ; readLength = readline(fd : %addr(textData) : %len(textData)); if readLength < 1; QOA.eof = *on; return; endif; qcustcdt.cusnum = %dec(%subst(textData : 2: 6) : 6 : 0); qcustcdt.lstnam = %subst(textData : 8 : 8); qcustcdt.init = %subst(textData : 16 : 3); qcustcdt.street = %subst(textData : 19 : 13); qcustcdt.city = %subst(textData : 32 : 6); qcustcdt.state = %subst(textData : 38 : 2); qcustcdt.zipcod = %dec(%subst(textData : 41 : 5) : 5 : 0); qcustcdt.cdtlmt = %dec(%subst(textData : 47 : 4) : 4 : 0); qcustcdt.chgcod = %dec(%subst(textData : 52 : 1) : 1 : 0); qcustcdt.baldue = %dec(%subst(textData : 54 : 7) : 6 : 2); qcustcdt.cdtdue = %dec(%subst(textData : 62 : 7) : 6 : 2); return; endif; //********************************************************* // CLOSE operation //********************************************************* if opcode = QrnOperation_CLOSE; callp close(fd); return; endif; /end-free P e

Code notes

A — the bnddir and /copy statements identify the resources used by the IFSHDLR3 service program. For more information about the values used, see Scott Klement’s IFS resources on his website.

B — the ifsHandler procedure is defined as an export procedure. The QOA parameter is passed to the procedure when the handler procedure is invoked.

C — the qcustcdt data structure is defined as an external data structure, with the qualified keyword. The data structure is based on the QOA.inputBuffer pointer, which points to the record format area for the qcustcdt file defined in the client program.

D — the fields defined in this section are used in the open, readline and close procedures defined in the IFS service programs. The fd variable (file descriptor) is defined as static so that it retains its value across invocations to the ifsHandler procedure.

E — the error constant is defined using the error number defined in the ILE RPG Reference manual.

F — the RPG open operation handler calls the IFS open operation for the /rpgoa/qcustcdt.txt file. The value returned by the IFS open will be zero or greater if the file is successfully opened. If the value is less than zero, an error has occurred and the QOA.rpgStatus field (defined on page 27) is set to indicate that an error occurred. Upon returning to the client (program IFS03), the %error built-in function is tested. If the file is opened successfully, the value assigned to fd is retained as a static variable for the subsequent read and close operations.

G

H

I

Page 16: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

14

G — the RPG read operation handler calls the IFS readline procedure (see page 8). The readline procedure takes the fd variable as its first parameter to identify the IFS file to be processed. The second parameter is the address of the textData character field; any data retrieved by the readline procedure will be available within that field. The third parameter is the length of the textData field, and is used to indicate to the readline procedure the “record length” it is to work with. Upon returning from readline, the readLength field contains the number of bytes read. If the readLength is less than one, there is no more data available in the text file. The QOA.eof flag (defined on page 28) is set to indicate to the client program that “end of file” has been reached. The %eof built-in function is tested in the IFS03 program after the read operation.

H — if a “record” was read in the readline procedure, it is split into the fields defined in the qcustcdt data structure. The substring positions are determined by examining the text file and the DSPFFD listing of the QCUSTCDT file. Moving the substring values into the qcustcdt subfields makes the data from the text file available to the caller. Because the qcustcdt data structure is based on the QOA.inputBuffer pointer, upon return from the handler to the caller (IFS03), the database file’s CUSREC record format is now filled with values. The IFS03 program has access to the field values, the same as if the values had been supplied by database management within that program.

Note that there is no data type checking perfomed in this example, which could lead to an error condition. If any of the numeric values do not contain valid numeric data, the caller (IFS03) will throw an invalid decimal data error upon returning from the read handler.

I — the RPG close operation is handled by calling the IFS close procedure, passing it the value of the fd variable. The IFS close procedure returns a value to indicate the success or failure of the close, but in this example, an error on the close is disregarded.

Page 17: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

How

The file i

The

w are the s

substring sttself and by

DSPFFD listin

ubstring p

tart positiony using the l

ng of the QC

ositions de

ns used in thlength of ea

USTCDT file i

etermined?

he read hanach field, as

s shown her

15

?

ndler (at sec defined in t

re for refere

ction H) are the QCUSTCDT

ence.

determinedT database

d by examinfile.

ning the text

t

Page 18: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

Figurblank

Figur

re 8: This is tk character p

re 9: This is t

the debug viepreceding eac

the hex-dump

ew of the texch numeric fie

p view of the

tData field. Ield.

e textData fiel

16

t represents

ld.

a "row" of daata read from

m the text file

ifs0e. There is a

ifs0

8

9

Page 19: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

The (“fileblanare p

To dfor. extraposit

The its le

Outp

The from

Figurwas a

qcustcdt.tx

e download”k before eapositive valu

determine thIn the followacts the valtion 2 for a

remaining sength, and t

qc qc qc qc qc qc qc qc qc qc qc

put of the

output of thm the /rpgoa

re 10: This isassigned to e

xt file was c”). The downch numeric ues, the sig

he starting pwing code frue of the cu length of 6

substring stthe leading

custcdt.cusncustcdt.lstnacustcdt.init custcdt.streecustcdt.city custcdt.statecustcdt.zipcocustcdt.cdtlmcustcdt.chgcocustcdt.baldcustcdt.cdtd

IFS03 prog

he IFS03 proa/qcustcdt.t

s the output oeach field in t

created by tnload was to field for then character

position withrom the IFSusnum. Inste characters.

arting positblank (sign)

um = %dec(%sam = %s = %set = %s = %se = %sod = %dec(%smt = %dec(%sod = %dec(%sue = %dec(%sue = %dec(%s

gram

ogram is shotxt file usin

of the IFS03 pthe CUSREC r

he IBM i Aco a File Type sign chara is left blank

hin the textHDLR3 prograd of startin

ions are cal) character.

ubst(textDatubst(textDatubst(textDatubst(textDatubst(textDatubst(textDatubst(textDatubst(textDatubst(textDatubst(textDatubst(textDat

own in Figurg the IFSHDL

program. All record forma

17

cess for Wine ASCII texcter. Becauk.

Data field, tram, the firsng a position

culated usin

a : 2: 6)a : 8 : 8)a : 16 : 3)a : 19 : 13)a : 32 : 6)a : 38 : 2)a : 41 : 5)a : 47 : 4)a : 52 : 1)a : 54 : 7)a : 62 : 7)

re 10. All ofLR3 handler

of the rows ht.

ndows Data xt. The Datase all of the

the leading sst substring n 1 of textD

ng the starti

) : 6 : 0); ); ); ); ); ); ) : 5 : 0); ) : 4 : 0); ) : 1 : 0); ) : 6 : 2); ) : 6 : 2);

f the data sh program.

have been re

Transfer fr Transfer pr

e numeric fi

sign charact operation Data, the su

ing position

hown in the

etreived from

om System rogram put eld values i

ter must bein the textDbstring star

of the prev

figure was

the text file,

i program a leading n the file

e accounted Data field rts at

vious field,

retrieved

ifs1 and the data

0 a

Page 20: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

18

Parameterizing the name of the IFS file In the IFSHDLR3 procedure, the name of the IFS file to read is hard-coded (see the code for the open operation at section F on page 12). The code is also shown here for review.

//********************************************************* // OPEN operation //********************************************************* if opcode = QrnOperation_OPEN; fd = open('/rpgoa/qcustcdt.txt' : O_RDONLY + O_TEXTDATA); if fd < 0; QOA.rpgStatus = ERROR_EXPLICIT_OPEN_CLOSE; endif; return; endif;

Obviously, it is not a good idea to hard-code the name of the file into the handler program.

The most likely use-case for this handler is that the client RPG program will determine the name of the IFS file to be processed. The issue is, how will the value of the name be conveyed from the RPG client program to the handler procedure?

RPG Open-Access provides an optional second parameter on the HANDLER keyword. The second parameter is the name of a variable that is defined in the client program. The variable can be a simple variable (for example, a character string variable). The variable can also be the name of a data structure, which can include any number of subfields. By using a data structure, you can pass any number of values to the handler. The single variable or the data structure with one or more subfields amounts to a user-defined parameter list.

When the handler program is invoked, the value of the second parameter on the HANDLER keyword is made available to the handler, in addition to the other data passed in the QrnOpenAccess data structure (the implicit first parameter that is always passed to the handler).

Data Structure ifsDS_t This data structure defines the template for the ifsDS data structure. It is used to pass the complete path and file name of the IFS file to work with from the client program to the handler.

**************************************************************** * Data Structure template ifsDS_t * * This data structure is used to define parameters that are * passed from the RPG client program to the handler. * * It can be considered to be a user-defined "parameter list" * of parameters to be passed. * * It is passed in addition to the implicitly passed * QrnOpenAccess parameter. **************************************************************** D ifsDS_t ds template D pathFileName... D 1024 varying

Page 21: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

19

RPG program IFS04 This program is a copy of the IFS03 program. It sets the value of the pathFileName data structure subfield that is passed in the optional second parameter data structure on the handler keyword.

H option(*srcstmt : *nodebugio) H bnddir('IFSHDLR') H dftactgrp(*no) **************************************************************** * Define the file and its handler. **************************************************************** Fqcustcdt IF E DISK usropn F handler(ifsHandler : F ifsDS) Fqsysprt O F 132 PRINTER /copy QOAR/QRPGLESRC,QRNOPENACC /copy PELKIE/QRPGLESRC,IFSDS **************************************************************** * The prototype for the ifsHandler procedure. * The QOA parameter is passed to the procedure. **************************************************************** D ifsHandler pr D QOA likeds(QrnOpenAccess_T) **************************************************************** * Define the optional handler parameter based on the * ifsDS_t template data structure. **************************************************************** D ifsDS ds likeds(ifsDS_t) /free *inlr = *on; //********************************************************* // set the complete path and file name of the IFS file //********************************************************* ifsDS.pathFileName = '/rpgoa/qcustcdt.txt'; //********************************************************* // Open the file. If any error on open, print error // message, end program. //********************************************************* open(e) qcustcdt; if %error; except error; return; endif; //********************************************************* // Go into "read loop" to read records from the file. //********************************************************* dow 1 = 1; read(e) qcustcdt; if %eof or %error; leave; endif; except qcust; enddo; //********************************************************* // Close the file. //********************************************************* close qcustcdt; /end-free

(continues)

A

B

C

Page 22: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

20

Oqsysprt E error 1 O 'Error on open' Oqsysprt E qcust 1 O cusnum O lstnam +2 O init +2 O street +2 O city +2 O state +2 O zipcod +2 O cdtlmt +2 O chgcod +2 O baldue +2 O cdtdue +2

Handler program IFSHDLR4 This handler is a copy of the IFSHDLR3 handler. This handler includes the ifsDS data structure to access the value of the pathFileName that was set in the IFS04 client program.

H nomain H option(*srcstmt : *nodebugio) H bnddir('QC2LE') H bnddir('IFSEBOOK/IFSTEXT') /copy IFSEBOOK/QRPGLESRC,IFSIO_H /copy IFSEBOOK/QRPGLESRC,IFSTEXT_H /copy QOAR/QRPGLESRC,QRNOPENACC /copy PELKIE/QRPGLESRC,IFSDS **************************************************************** * Procedure ifsHandler * * This procedure receives control when invoked by RPG-OA * in a client program. The QOA parameter is implicitly * passed. **************************************************************** PifsHandler B export D PI D QOA likeds(QrnOpenAccess_T) **************************************************************** * The QCUSTCDT structure is based on the QOA.inputBuffer * pointer. It is the storage for the record format in * the client program. **************************************************************** D qcustcdt e ds extname('QIWS/QCUSTCDT') D qualified D based(QOA.inputBuffer) **************************************************************** * The ifsDS data structure is based on the QOA.userArea * pointer. IT is the storage for the optional parameter * area that is set inthe client program. **************************************************************** D ifsDS ds likeds(ifsDS_t) D based(QOA.userArea) **************************************************************** * The opcode is one of the supported file I/O opcodes. **************************************************************** D opcode s like(QOA.rpgOperation) **************************************************************** * These fields are used with the IFS read procedures. * * fd - file descriptor, provides a "handle" to the * IFS file. Coded as static so that it keeps * its value across invocations of the procedure. * readLength - the length of the data returned from the * call to the readline procedure. * textData - the data that is returned as a "record" from * the text file. **************************************************************** D fd s 10i 0 static D readLength s 10i 0 D textData s 68

(continues)

See userArea defined on page 27

A

Page 23: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

21

**************************************************************** * Define RPG status code for errors * (see ILE RPG Reference, "File Exception/Errors") **************************************************************** D ERROR_EXPLICIT_OPEN_CLOSE... D c 01217 /free opcode = QOA.rpgOperation; //********************************************************* // OPEN operation //********************************************************* if opcode = QrnOperation_OPEN; fd = open(ifsDS.pathFileName : O_RDONLY + O_TEXTDATA); if fd < 0; QOA.rpgStatus = ERROR_EXPLICIT_OPEN_CLOSE; endif; return; endif; //********************************************************* // READ operation //********************************************************* if opcode = QrnOperation_READ; readLength = readline(fd : %addr(textData) : %len(textData)); if readLength < 1; QOA.eof = *on; return; endif; qcustcdt.cusnum = %dec(%subst(textData : 2: 6) : 6 : 0); qcustcdt.lstnam = %subst(textData : 8 : 8); qcustcdt.init = %subst(textData : 16 : 3); qcustcdt.street = %subst(textData : 19 : 13); qcustcdt.city = %subst(textData : 32 : 6); qcustcdt.state = %subst(textData : 38 : 2); qcustcdt.zipcod = %dec(%subst(textData : 41 : 5) : 5 : 0); qcustcdt.cdtlmt = %dec(%subst(textData : 47 : 4) : 4 : 0); qcustcdt.chgcod = %dec(%subst(textData : 52 : 1) : 1 : 0); qcustcdt.baldue = %dec(%subst(textData : 54 : 7) : 6 : 2); qcustcdt.cdtdue = %dec(%subst(textData : 62 : 7) : 6 : 2); return; endif; //********************************************************* // CLOSE operation //********************************************************* if opcode = QrnOperation_CLOSE; callp close(fd); return; endif; /end-free P e

B

Page 24: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

22

RPG copy source QOAR/QRPGLESRC(QRPNOPENACC)

Note: the source code shown here is a reformatted version of the original IBM source member. The comments have been moved to comment blocks, rather than “inline” comments.

/* begin_generated_IBM_copyright_prolog */ /* This is an automatically generated copyright prolog. */ /* After initializing, DO NOT MODIFY OR MOVE */ /* ----------------------------------------------------------------- */ /* */ /* Product(s): */ /* 5733-OAR */ /* */ /* (C)Copyright IBM Corp. 2010, 2010 */ /* */ /* All rights reserved. */ /* US Government Users Restricted Rights - */ /* Use, duplication or disclosure restricted */ /* by GSA ADP Schedule Contract with IBM Corp. */ /* */ /* Licensed Materials-Property of IBM */ /* */ /* --------------------------------------------------------------- */ /* */ /* end_generated_IBM_copyright_prolog */ /*** START HEADER FILE SPECIFICATIONS *********************** */ /* */ /*Header File Name: QRNOPENACC */ /* */ /*Descriptive Name: API error numbers. */ /* */ /*Change Activity: */ /* */ /*CFD List: */ /* */ /*FLAG REASON LEVEL DATE PGMR CHANGE DESCRIPTION */ /*---- ------------ ----- ------ --------- ---------------------- */ /*$A0= 090830 BLM New Include */ /* */ /*End CFD List. */ /* */ /*Additional notes about the Change Activity */ /*End Change Activity. */ /*** END HEADER FILE SPECIFICATIONS ****************************** */ /IF DEFINED(QrnOpenAccess_Included) /EOF /ENDIF /DEFINE QrnOpenAccess_Included /* Format of QrnOpenAccess struct */ D ROIO0100 C 'ROIO0100' *************************************************************** * Device Types *************************************************************** D QrnDevice_Database... D C 'D' D QrnDevice_Printer... D C 'P' D QrnDevice_UserInterface... D C 'U'

Page 25: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

23

*************************************************************** * Operations *************************************************************** D QrnOperation_OPEN... D C 1 D QrnOperation_POSITION_START... D C 2 D QrnOperation_POSITION_END... D C 3 D QrnOperation_READ... D C 4 D QrnOperation_READC... D C 5 D QrnOperation_READE... D C 6 D QrnOperation_READP... D C 7 D QrnOperation_READPE... D C 8 D QrnOperation_CHAIN... D C 9 D QrnOperation_EXFMT... D C 10 D QrnOperation_SETGT... D C 11 D QrnOperation_SETLL... D C 12 D QrnOperation_UNLOCK... D C 13 D QrnOperation_UPDATE... D C 14 D QrnOperation_WRITE... D C 15 D QrnOperation_DELETE... D C 16 D QrnOperation_FEOD... D C 17 D QrnOperation_CLOSE... D C 18 D QrnOperation_DELETE_CURRENT... D C 19 D QrnOperation_READE_CURRENT... D C 20 D QrnOperation_READPE_CURRENT... D C 21 *************************************************************** * Function Keys *************************************************************** D QrnFunctionKey_None... D C 0 D QrnFunctionKey_01... D C 1 D QrnFunctionKey_02... D C 2 D QrnFunctionKey_03... D C 3 D QrnFunctionKey_04... D C 4 D QrnFunctionKey_05... D C 5 D QrnFunctionKey_06... D C 6 D QrnFunctionKey_07... D C 7 D QrnFunctionKey_08... D C 8 D QrnFunctionKey_09... D C 9 D QrnFunctionKey_10... D C 10 D QrnFunctionKey_11... D C 11 D QrnFunctionKey_12... D C 12 D QrnFunctionKey_13... D C 13 D QrnFunctionKey_14... D C 14 D QrnFunctionKey_15... D C 15 D QrnFunctionKey_16... D C 16 D QrnFunctionKey_17... D C 17

QrnOperation_OPEN

QrnOperation_READ

QrnOperation_CLOSE

Page 26: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

24

D QrnFunctionKey_18... D C 18 D QrnFunctionKey_19... D C 19 D QrnFunctionKey_20... D C 20 D QrnFunctionKey_21... D C 21 D QrnFunctionKey_22... D C 22 D QrnFunctionKey_23... D C 23 D QrnFunctionKey_24... D C 24 D QrnFunctionKey_PRINT... D C 121 D QrnFunctionKey_ROLLUP... D C 122 D QrnFunctionKey_ROLLDOWN... D C 123 D QrnFunctionKey_CLEAR... D C 124 D QrnFunctionKey_HELP... D C 125 D QrnFunctionKey_HOME... D C 126 *************************************************************** * Data Types *************************************************************** D QrnDatatype_Alpha... D C 1 D QrnDatatype_AlphaVarying... D C 2 D QrnDatatype_Unicode... D C 3 D QrnDatatype_UnicodeVarying... D C 4 D QrnDatatype_Dbcs... D C 5 D QrnDatatype_DbcsVarying... D C 6 D QrnDatatype_Indicator... D C 7 D QrnDatatype_Decimal... D C 8 D QrnDatatype_Integer... D C 9 D QrnDatatype_Unsigned... D C 10 D QrnDatatype_Float... D C 11 D QrnDatatype_Date... D C 12 D QrnDatatype_Time... D C 13 D QrnDatatype_Timestamp... D C 14 *************************************************************** * Date Formats *************************************************************** D QrnDtzFormat_ISO... D C 1 D QrnDtzFormat_USA... D C 2 D QrnDtzFormat_EUR... D C 3 D QrnDtzFormat_JIS... D C 4 D QrnDtzFormat_YMD... D C 5 D QrnDtzFormat_MDY... D C 6 D QrnDtzFormat_DMY... D C 7 D QrnDtzFormat_JUL... D C 8 D QrnDtzFormat_HMS... D C 9

Page 27: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

25

*************************************************************** * Template - Print Control *************************************************************** D QrnPrtctl_T... D DS QUALIFIED TEMPLATE D spaceBefore 3S 0 D spaceAfter 3S 0 D skipBefore 3S 0 D skipAfter 3S 0 D currLine 3S 0 *************************************************************** * Template - Record Level *************************************************************** D QrnRecordLevel_T... D DS QUALIFIED TEMPLATE D record 10A D level 13A *************************************************************** * Template - Record Levels *************************************************************** D QrnRecordLevels_T... D DS QUALIFIED TEMPLATE ALIGN D num 10I 0 D levels LIKEDS(QrnRecordLevel_T) D DIM(32767) *************************************************************** * Template - Object Name *************************************************************** D QrnObject_T... D DS QUALIFIED TEMPLATE D name 10A D library 10A *************************************************************** * Template - Name/Value * * externalName I Name from external file * dataType I Data type of field (QrnDatatype_*) * numericDefinedLen I Defined lenght of numeric * - Decimal: total digits * - Integer: bytes * - Unsigned: bytes * - Float: bytes * Numeric fields only * decimals I Decimal places of field, * - decimal fields only * dtzFormat I Date/time/timestamp format * - date/time/timestamp only * dtSeparator I Date/time separator * - date/time only * input I Input field (set by handler) * output I Output field (used by handler) * isNullCapable I Is the field null capable * hasNullValue I/O Does field have null value * reserved1 Hex zeros * valueLenBytes I/O Length of value in bytes * valueMaxLenBytes I Maximum lenght in bytes * valueCcsid I CCSID of the value * reserved2 Zero * value I/O Field value in human-readable form * reserved3 Null *************************************************************** D QrnNameValue_T... D DS QUALIFIED TEMPLATE D externalName... D 10A D dataType... D 3U 0 D numericDefinedLen... D 3U 0 D decimals... D 3U 0 D dtzFormat... D 3U 0 D dtSeparator... D 1A D input... D N D output... D N D isNullCapable... D N D hasNullValue...

Page 28: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

26

D N D reserved1... D 13A D valueLenBytes... D 10U 0 D valueMaxLenBytes... D 10U 0 D valueCcsid... D 10I 0 D reserved2... D 10U 0 D value... D * D reserved3... D * *************************************************************** * Template - Names/Values *************************************************************** D QrnNamesValues_T... D DS QUALIFIED TEMPLATE ALIGN D num 10I 0 D field LIKEDS(QrnNameValue_T) D DIM(32767) *************************************************************** * Template - Open Access * * length I Length of this structure * reserved1 Zero * parameterFormat I Format of this structure ROACnnnn * userArea I/O User area owned by the RPG program * stateInfo I/O State info owned by the handler * recordLevels I Record format level indicators * - NULL if file is program described * inputBuffer O Input buffer, NULL if not used by opcode * - length is given by inputBufferLen * inputNullMap O Input null byte map * - Length is given by inputNullMapLen * outputBuffer I Output buffer, NULL if not used by opcode * - Length is given by outputBufferLen * outputNullMap I Output null byte map * - Length is given by outputNullMapLen * namesValues I/O Alternate version of I/O buffer information * key I Key, NULL if not used by opcode * - Length is given by keyLen * keyNullMap I Key null byte map * - Length is given by keyNullMapLen * keynamesValues I Alternate version of key information * indara I/O Indicator array, dim99 * NULL if not used by file or if * using names-values * prtctl I Print control * openFeedback O The handler can set this pointer * - Length is specified in openFeedbackLen * ioFeedback O The handler can set this pointer * - Length is specified in ioFeedbackLen * deviceFeedback O The handler can set this pointer * - Length is specified in deviceFeedbackLe * reserved2 I NULL * reserved3 I NULL * reserved4 I NULL * externalFile I External file * externalMember I External member * compileFile I File used at compile time * recordName I/O Record name * reserved5 I Hex zeros * rpgOperation I RPG operation, see QrnOperation_* * rpgStatus O RPG status code * inputBufferLen I Length of input buffer * inputNullMapLen I Length of input null map * outputBufferLen I Length of output buffer * outputNullMapLen I Length of output null map * keyLen I Length of key * keyNullMapLen I Length of key null map * inputDataLen O Length of input data * openFeedbackLen O Length of open feedback * ioFeedbackLen O Length of I/O feedback * deviceFeedbackLen O Length of device feedback * numKeys I Number of key fields * N/A for program described file * rrn I/O RRN * formLen I Printer form length * Only meaningful for program described PRI * formOfl I Printer form overflow * Only meaningful for program described PRI

Page 29: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

27

* reserved6 Zero * reserved7 Zero * reserved8 Zero * reserved9 Zero * functionKey O F1-F24, PRINT, ROLLUP, etc. * See QrnFunctionKey_* * Unknown values cause RPG exception * externallyDescribed I Externally described file * keyedFile I RPG keyed access * blocked I BLOCK(*YES) * eof O EOF * found O Record found * equal O Key is equal * printerOverflow O Page overflow reached * inputWithLock I Input operation with lock * useNamesValues I/O Whether the operation will use the name-val * info rather than the I/O buffers * Set by handler during OPEN operation, * used by handler and RPG for I/O operation * isSubfile I Is the record defined as a subfile * reservedInds I '0' * rpgDevice I See QrnDevice_* * reserved10 I Hex zeros * *************************************************************** D QrnOpenAccess_T... D DS TEMPLATE QUALIFIED ALIGN D length... D 10U 0 D reserved1... D 10U 0 D parameterFormat... D 8A D userArea... D * D stateInfo... D * D recordLevels... D * D inputBuffer... D * D inputNullMap... D * D outputBuffer... D * D outputNullMap... D * D namesValues... D * D key... D * D keyNullMap... D * D keynamesValues... D * D indara... D * D prtctl... D * D openFeedback... D * D ioFeedback... D * D deviceFeedback... D * D reserved2... D * D reserved3... D * D reserved4... D * D externalFile... D LIKEDS(QrnObject_T) D externalMember... D 10A D compileFile... D LIKEDS(QrnObject_T) D recordName... D 10A D reserved5... D 20A D rpgOperation... D 10U 0 D rpgStatus... D 10I 0

rpgOperation

rpgStatus

inputBuffer

userArea

Page 30: Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to read from the text file in the IFS. It returns a “record” to the caller on

28

D inputBufferLen... D 10U 0 D inputNullMapLen... D 10U 0 D outputBufferLen... D 10U 0 D outputNullMapLen... D 10U 0 D keyLen... D 10U 0 D keyNullMapLen... D 10U 0 D inputDataLen... D 10U 0 D openFeedbackLen... D 10U 0 D ioFeedbackLen... D 10U 0 D deviceFeedbackLen... D 10U 0 D numKeys... D 10U 0 D rrn... D 10U 0 D formLen... D 10U 0 D formOfl... D 10U 0 D reserved6... D 10U 0 D reserved7... D 10U 0 D reserved8... D 10U 0 D reserved9... D 10U 0 D functionKey... D 3U 0 D externallyDescribed... D 1N D keyedFile... D 1N D blocked... D 1N D eof... D 1N D found... D 1N D equal... D 1N D printerOverflow... D 1N D inputWithLock... D 1N D usenamesValues... D 1N D isSubfile... D 1N D reservedInds... D 1N DIM(5) D rpgDevice... D 1A D reserved10... D 31A *************************************************************** * E N D O F M E M B E R ***************************************************************

eof