Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to...
Transcript of Create an IFS Handler using RPG Open-Access · 2020. 2. 12. · The readline procedure is called to...
Create an IFS Handler using
RPG Open-Access Craig Pelkie [email protected]
Create an IFS Handler using RPG Open-Access 2012-07-20
Copyright © 2012, Craig Pelkie, ALL RIGHTS RESERVED
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
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
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
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)
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
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
.
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
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
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.
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
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
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
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
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
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
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.
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
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
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
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
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
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
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
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'
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
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
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...
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
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
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