|
On Tue, 24 Feb 2004, Wim wrote:
> Yes, I either declare it as type *X or as *char Len(1). Am I right in
> assuming that the definition in the command is merely for the compiler to do
> some preliminary type checking?
When you use TYPE(*X) it's also required that you pass VARY(*YES) and
PASSATR(*YES), I believe. If you overwrote the special bytes that go at
the start of a string when you use PASSATR(*YES) or VARY(*YES), it could
certainly cause the error that you're describing.
Likewise, if you define it as TYPE(*CHAR) with VARY(*YES) and overwrite
the first two bytes with incorrect data, you'll get an error.
You also have to be very careful not to exceed the space that has been
allocated to the variable. For example, if the variable is
TYPE(*CHAR) LEN(10), and your RPG does a myKeyVal = *blanks you'll write
blanks not only to the 10 bytes of of passed variable, but also to the
2038 bytes after it, so you have to do something like:
%subst(myKeyVal: 1: myKeyValLen) = *blanks
To make sure that you don't write blanks into areas of memory that you
weren't supposed to access (and therefore causing random errors to occur)
In an effort to better understand your predicament, I wrote some test
programs, which worked in my environment. One that used type(*X) and one
that used type(*CHAR). As I said, these work for me -- though I didn't
test them very thoroughly. Perhaps looking at them will help you get on
the right track.
First example: Using type(*X) -- note that a separate length does NOT
need to be passed because the length is already sent as part of the
parameter, compliments of VARY(*YES)
CL program that runs RTVQ:
PGM
DCL VAR(&TYPE) TYPE(*CHAR) LEN(100) VALUE('TEST')
RTVQ FILE('/DOESNT/REALLY/MATTER.TXT') KEY('TYPE') +
KEYVAL(&TYPE)
SNDPGMMSG MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA(&TYPE) +
MSGTYPE(*COMP)
ENDPGM
Command source:
CMD PROMPT(TEST)
PARM KWD(FILE) TYPE(*PNAME) LEN(2048) MIN(1) +
PROMPT('File')
PARM KWD(KEY) TYPE(*CHAR) LEN(10) MIN(1) +
PROMPT('Key')
PARM KWD(KEYVAL) TYPE(*X) LEN(1) RTNVAL(*YES) +
MIN(1) VARY(*YES *INT2) PASSATR(*YES) +
PROMPT('CL var for returned key value')
CPP for RTVQ, written in ILE RPG (I used /FREE, though you could do the
same thing in fixed-format):
H DFTACTGRP(*NO) OPTION(*SRCSTMT: *NODEBUGIO: *NOSHOWCPY)
D TypeX DS qualified based(prototype_only)
D Attr 1A
D Len 5I 0
D Data 2048A
D QMHSNDPM PR ExtPgm('QMHSNDPM')
D MessageID 7A Const
D QualMsgF 20A Const
D MsgData 32767A const options(*varsize)
D MsgDtaLen 10I 0 Const
D MsgType 10A Const
D CallStkEnt 10A Const
D CallStkCnt 10I 0 Const
D MessageKey 4A
D ErrorCode 32767A options(*varsize)
D dsEC DS qualified
D BytesPrv 10I 0 inz(0)
D BytesAvl 10I 0 inz(0)
D Msg s 100A varying
D MsgKey s 4A
D RTVQR4 PR ExtPgm('RTVQR4')
D peFile 2048A const
D peKey 10A const
D peKeyVal likeds(TypeX) options(*varsize)
D RTVQR4 PI
D peFile 2048A const
D peKey 10A const
D peKeyVal likeds(TypeX) options(*varsize)
/free
if (peKeyVal.attr <> x'04');
Msg = 'You must pass a *CHAR variable for KEYVAL';
QMHSNDPM( 'CPF9897'
: 'QCPFMSG *LIBL'
: Msg
: %len(Msg)
: '*ESCAPE'
: '*'
: 2
: MsgKey
: dsEC);
endif;
%subst(peKeyVal.data: 1: peKeyVal.Len) = *blanks;
select;
when peKey = 'TYPE';
%subst(peKeyVal.data: 1: peKeyVal.Len) = *all'T';
when peKey = 'NOTTYPE';
%subst(peKeyVal.data: 1: peKeyVal.Len) = *all'N';
other;
%subst(peKeyVal.data: 1: peKeyVal.Len) = *all'O';
endsl;
*inlr = *on;
/end-free
Here's the example that uses TYPE(*CHAR). For this one, I tried to do
exactly what you described in your message, and used LEN(1) with
VARY(*NO). (Since VARY would most likely not work when I specify LEN(1),
anyway...) and that means that I need a separate KEYVALLEN parameter:
PGM
DCL VAR(&TYPE) TYPE(*CHAR) LEN(100) VALUE('TEST')
RTVQ2 FILE('/DOESNT/REALLY/MATTER.TXT') KEY('TYPE') +
KEYVAL(&TYPE) KEYVALLEN(100)
SNDPGMMSG MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA(&TYPE) +
MSGTYPE(*COMP)
ENDPGM
CMD PROMPT(TEST)
PARM KWD(FILE) TYPE(*PNAME) LEN(2048) MIN(1) +
PROMPT('File')
PARM KWD(KEY) TYPE(*CHAR) LEN(10) MIN(1) +
PROMPT('Key')
PARM KWD(KEYVAL) TYPE(*CHAR) LEN(1) RTNVAL(*YES) +
MIN(1) PROMPT('CL var for returned key +
value')
PARM KWD(KEYVALLEN) TYPE(*DEC) LEN(4 0) MIN(1) +
PROMPT('Length of KEYVAL')
H DFTACTGRP(*NO) OPTION(*SRCSTMT: *NODEBUGIO: *NOSHOWCPY)
D RTVQR4 PR ExtPgm('RTVQR4')
D peFile 2048A const
D peKey 10A const
D peKeyVal 2048A options(*varsize)
D peKeyValLen 4P 0 const
D RTVQR4 PI
D peFile 2048A const
D peKey 10A const
D peKeyVal 2048A options(*varsize)
D peKeyValLen 4P 0 const
/free
%subst(peKeyVal: 1: peKeyValLen) = *blanks;
select;
when peKey = 'TYPE';
%subst(peKeyVal: 1: peKeyValLen) = *all'T';
when peKey = 'NOTTYPE';
%subst(peKeyVal: 1: peKeyValLen) = *all'N';
other;
%subst(peKeyVal: 1: peKeyValLen) = *all'O';
endsl;
*inlr = *on;
/end-free
Hope that answers your question...
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2025 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.