Let's say I have this program interface
d PgmText pi
d outInfo 65535
d pgmName 10 const
d pgmLibrary 10 const
I'm calling it through JTOpen
, which then reads the data assigned to the input/output parameter outInfo
. The issue is that the %alloc
-ated data exceeds the maximum dimension of outInfo
.
Thus, what should I do?
E.g. I could pass an AS400ByteArray
as ProgramParameter.PASS_BY_REFERENCE
, but then what do I do in the RPG code?
N.B. it must be compatible with V5R1.
It seems the best possible choice is the User Space.
For example, let's say we need to extract the source code from a *PGM
object, which we'll then read from JTOpen
. To accomplish that, we write the following RPG program, which given a *PGM
qualified path and a *USRSPC
qualified path, writes to that User Space.
From the JVM layer, simply ProgramCall
this RPG program, and then read with a UserSpace
.
h dftactgrp(*no)
**
* This program writes to a UserSpace with the following layout:
*
* Total lines number | CHAR(10)
* [for every line]
* Sequence number | CHAR(6)
* Last edit date | CHAR(6)
* Source line | CHAR(*) (lineLength - 12)
*
* @author Edoardo Luppi
**
d PgmText pr extpgm('PGMTEXT')
d qProgramName 20 const
d qUsrspcName 20 const
d lineLength 10i 0 const
d PgmText pi
d qProgramName 20 const
d qUsrspcName 20 const
d lineLength 10i 0 const
* Internal procedures
d startSourceDebug...
d pr
d retrieveTextViewNumber...
d pr 10i 0
d retrieveViewId...
d pr 10i 0
d viewNumber 10i 0 value
d writeLinesToUserSpace...
d pr
d viewId 10i 0 value
/copy qcopysrc,qusrspc
/copy qcopysrc,qdebug
d errorCode ds qualified
d bytesProvided 10i 0 inz(%size(errorCode))
d bytesAvailable...
d 10i 0 inz
d exceptionId 7
d 1
d exceptionData 512
* QteRetrieveModuleViews
d vewl0100 ds qualified
d bsReturned 10i 0 inz
d bsAvailable 10i 0 inz
d numOfElements 10i 0 inz
d vewl0100Element...
d ds qualified based(vewl0100ElementPtr)
d moduleName 10
d viewType 10
d compilerId 20
d mainIndicator 10
d viewTimestamp 13
d viewDescription...
d 50
d 3
d viewNumber 10i 0
d numberOfViews 10i 0
d vewl0100ElementPtr...
d s *
* QteRetrieveViewText
d textViewStruct ds qualified
d bsReturned 10i 0 inz
d bsAvailable 10i 0 inz
d numOfElements 10i 0 inz
d lineLength 10i 0 inz
d textViewStructElement...
d ds qualified based(textViewElementPtr)
d sequenceNum 12
d sourceLine 500
d textViewElementPtr...
d s *
* Common variables
d viewId s 10i 0 inz
d numOfLines s 10i 0 inz
d returnedLib s 10 inz
d viewTimestamp s 13 inz
d receiverVar s 32000 inz
d textViewNumber s 3i 0 inz
d programName s 10 inz
/free
programName = %subst(qProgramName:1:10);
startSourceDebug();
textViewNumber = retrieveTextViewNumber();
if (textViewNumber >= 0);
viewId = retrieveViewId(textViewNumber);
writeLinesToUserSpace(viewId);
endif;
return;
/end-free
**
* Start the debug session and register the program-stop handler exit program.
**
p startSourceDebug...
p b
* Program-stop handler exit program path
d PSHEP c 'PGMSTOPHDLMYLIB '
/free
reset errorCode;
QteStartSourceDebug(PSHEP:errorCode);
/end-free
p e
**
* Find the *TEXT debug view's number.
**
p retrieveTextViewNumber...
p b
d pi 10i 0
d i s 10i 0 inz
/free
reset errorCode;
QteRetrieveModuleViews(
receiverVar:
%size(receiverVar):
'VEWL0100':
qProgramName:
'*PGM':
programName:
returnedLib:
errorCode
);
vewl0100 = receiverVar;
i = 0;
dow (i < vewl0100.numOfElements);
// 124 is the length of an element of the VEWL0100 structure
vewl0100ElementPtr = %addr(receiverVar) + 12 + (i * 124);
// We are interested in the *TEXT view only, which contains
// sequence numbers and their associated source lines
if (vewl0100Element.viewType = '*TEXT');
return vewl0100Element.viewNumber;
endif;
i += 1;
enddo;
// No *TEXT view found.
return -1;
/end-free
p e
**
* Get the debug View ID given its number.
**
p retrieveViewId...
p b
d pi 10i 0
d viewNumber 10i 0 value
d viewId s 10i 0 inz
/free
reset errorCode;
QteRegisterDebugView(
viewId:
numOfLines:
returnedLib:
viewTimeStamp:
qProgramName:
'*PGM':
programName:
textViewNumber:
errorCode
);
return viewId;
/end-free
p e
**
* Writes every line of the program's source, which has a fixed width,
* sequentially to the User Space.
**
p writeLinesToUserSpace...
p b
d pi
d viewId 10i 0 value
d data s 999 inz
d startLineNumber...
d s 10i 0 inz(1)
d linesPerPass s 10i 0 inz
d firstPass s n inz(*on)
d lineNumber s 10i 0 inz
d i s 10i 0 inz
/free
dow firstPass or textViewStruct.bsReturned < textViewStruct.bsAvailable;
reset errorCode;
reset receiverVar;
QteRetrieveViewText(
receiverVar:
%size(receiverVar):
viewId:
startLineNumber:
linesPerPass:
lineLength:
errorCode
);
firstPass = *off;
textViewStruct = receiverVar;
if (textViewStruct.bsReturned < textViewStruct.bsAvailable);
startLineNumber += textViewStruct.numOfElements;
linesPerPass = 1000;
endif;
i = 0;
dow (i < textViewStruct.numOfElements);
// The length of an occurrence depends on lineLength
textViewElementPtr = %addr(receiverVar) + 16 + (i * lineLength);
data = textViewStructElement.sequenceNum +
%subst(textViewStructElement.sourceLine:1:lineLength - 12);
Quschgus(
qUsrspcName:
10 + (lineNumber * lineLength + 1):
lineLength:
%subst(data:1:lineLength):
'0':
errorCode
);
lineNumber += 1;
i += 1;
enddo;
enddo;
Quschgus(qUsrspcName:1:10:%char(lineNumber):'0':errorCode);
/end-free
p e