- - -
The command has a parm defined as
PARM KWD(SGRP) TYPE(*DEC) LEN(2 0) DFT(*ALL) +
SNGVAL((*ALL -1)) MAX(10) PROMPT('Sales +
Group# (Or *ALL)')
- - -
The command processing cl accepts this parm as ONE long
PGM PARM(&LIST1)
DCL VAR(&LIST1) TYPE(*CHAR) LEN(1)
CALL RPGPGM PARM(&LIST)
The cl does nothing with this value except pass it a RPG program.
- - - -
The called RPG program accepts this parm. then uses the info from the DS
C *ENTRY PLIST
C PARM LIST1
D LIST1 DS
D #SG 1 2B 0
D SG 3 22P 0
D DIM(10)
D PACKEVEN
- - -
Now my question is How the heck does this work? The field the CL program
is clearly defined as 1 long character. The field LIST1 in the RPG program
is defined as 22 long. Yet this works fine. The RPG processes the parm
like a normal list parm..
I have always believed the parm attributes and length had to match between
CMD / CPP / and any called programs..
- - -
I needed to check the list values in the CL for some processing logic..
Imagine my surprise when I saw the list wasn't even defined in the CL!
(v4r4)
So in your example, the command parser is passing a pointer to a structure.
The CL program is setting the base address of the variable &LIST1 to the
value of that pointer. To be sure, if the CL program referenced the value of
&LIST is would only see the first byte. When the CL program calls the RPG
program, it also simply passes a pointer for each parameter. For &LIST1 the
value in the pointer happens to point at the same address that the command
passed to the CL program.
This is *VERY* common technique. I have used this technique to enable my OPM
programs to use ILE API's. I simply write an ILE CL wrapper and use 1 byte
parameters as place holders
"Craig Rutledge" <cra...@vol.com> wrote in message
news:Q7LH4.4184$hr2.9...@news-east.usenetserver.com...
It still looks kinda strange in the code though.
Guess I can take the rest of the day off now, I learned something new
today.
Thanks again.
- - -
Tim <scot...@home.com.xyz> wrote in message
news:48MH4.6202$T4.1...@news1.rdc1.ne.home.com...
(snip)
This thread pointed me in the right direction to fix a *different*
problem. We were writing a trigger program for a file with a large
variable length field in it.
As usual, we pulled on our trigger buffer description in from
another program:
* Trigger buffer
D TrgBuf DS 32767
D FileName 1 10
D LibName 11 20
D MbrName 21 30
D TrgEvent 31 31
D TrgTime 32 32
D ComtLckLvl 33 33
D CCSID 37 40B 0
D OldOff 49 52B 0
D OldLen 53 56B 0
D OldNullOff 57 60B 0
D OldNullLen 61 64B 0
D NewOff 65 68B 0
D NewLen 69 72B 0
D NewNullOff 73 76B 0
D NewNullLen 77 80B 0
D InsertEvt C Const('1')
D DeleteEvt C Const('2')
D UpdateEvt C Const('3')
The DS was set up with a length of 32767, the maximum allowed.
As usual, we pulled in the description of the file as an external
structure:
D RcdFmt e extname(ourfile)
and pulled the data from the after trigger into this structure using
%subst:
C eval Start = NewOff + 1
C eval RcdFmt = %subst(TrgBuf:Start:NewLen)
We have used this approach many times before, but this time it went
bang - our record was so large that the new record offset pointed
*outside* our 32767 structure, and we couldn't make the structure
any bigger.
It was it this point that I remembered that the AS/400 passes parame
ters*by reference*. This means that even if your parameter isn't
long enough to hold all the data, the data is still there. You just
can't usually see it. Pointers to the rescue!
We removed the 32767 from the trigger buffer structure - we can
really only rely on the first 80 anyway. We then added a based
pointer to the external file description:
D RcdFmt E DS extname(ourfile)
based(@RcdFmt)
and used the %addr BIF to position the pointer off in cyberspace
somewhere:
c eval @RcdFmt = %addr(BufTrg) + NewOff
And it worked!
This approach seems to me to have a couple of advantages. We don't
need an arbitrarily sized data structure, and because we aren't
copying records around it will be a bit quicker.
I hope someone finds this useful...
--
Cheers,
Simon Brunning
TriSystems Ltd.
sbru...@trisystems.co.uk
The opinions expressed are mine, and are not necessarily those of my
employer.