FWiW the reason I mentioned using HEX() originally was because the DS
was unknown; i.e. unstated\undefined in the OP. Well also because that
it was so convenient, given the program was SQLRPG. If there had been
any binary [e.g. integer or packed decimal] data declared in the DS,
then a x'7D' might be embedded in the data, and without that "hexify" of
the data any embedded apostrophes would be interpreted by the command
analyzer as just another apostrophe in the data; that is an issue both
for binary data as well as any character data [sub]fields, where the
0x7D character is the equivalent of an apostrophe anywhere in the binary
data. That same potential problem remains, with what is noted to be the
chosen "resolution". If none of the character [sub]fields defined in
the DS will ever have an embedded apostrophe and no binary data will
ever be added [or it will never contain 0x7D; unlikely, or at least
difficult to ensure] then the "simple" concatenation chosen as
"resolution" should work just fine.
I say "just fine" because in the example as the chosen "resolution",
the data is being passed as delimited string values in a command string,
rather than being passed as a CL variable. While specification of a CL
variable name for an argument of the PARM() would have the command
analyzer stripping the trailing blanks, my recollection is that the
fully padded delimited string will be passed in that same length of
storage; i.e. the length between the apostrophes. That is to imply,
while the request to SBMJOB CMD(CALL PGM(called) PARM(&DS)) would have
trailing blanks stripped from the data of the variable &DS, I do not
think that is a problem when the command string is fully evaluated with
the apostrophe as delimiter for the value passed as the parameter(s).
For example, consider a program CALLED which declares its only
parameter as *CHAR LEN(41), and the program CALLER which will issue a
CALL to program CALLED is setup with the following:
DCL &DS *CHAR 41 VALUE('....+....1....+....2....+....3....+....4 ')
DCL &DX *CHAR 42 /* set from &DS *CAT 'X' */
ChgVar &DX (&DS *CAT &DX)
If I SBMJOB CMD(CALL PGM(called) PARM(&DS)) then the Command Analyzer
prepares the CALL with 40-bytes of storage for the effective argument of
PARM('....+....1....+....2....+....3....+....4') which is one byte less
than is declared by the called program. Thus the 41st byte of data is
unpredictable.
If I SBMJOB CMD(CALL PGM(called) PARM(&DX)) then the Command Analyzer
prepares the CALL with 42-bytes of storage for the effective argument of
PARM('....+....1....+....2....+....3....+....4 X') which is one byte
more than is declared by the called program. Thus the 41st byte of data
is protected from truncation, and the 42nd byte is not /visible/ to the
called program because its declaration only /sees/ 41-bytes.
If I SBMJOB CMD(CALL PGM(called)
PARM('....+....1....+....2....+....3....+....4 ')) then the Command
Analyzer should treat this request the same as the interactive command
line invocation of CALL PGM(called)
PARM('....+....1....+....2....+....3....+....4 ') whereby the Command
Analyzer sees\respects the full delimited string of 41-bytes of data.?
I leave the question mark, even though I am fairly confident I am
correct that both requests would be treated identically and both work
perfectly fine; i.e. the trailing blank is safely passed\included in the
41-byte parameter declared by the called program.
Of course even if the trailing blanks would still impact the
evaluated string with delimited parameter values, the evaluated command
string could [even more easily than the &DX example] have an extra
non-blank byte added; e.g.:
Command = 'SBMJOB CMD(CALL PGM(PROVSN_NMS) PARM('''
+ NMS_OrderDetails + 'X''')) JOB(TESTING)';
Regards, Chuck
On 24 May 2012 14:55, DeLong, Eric wrote:
I think you're flirting with disaster... Perhaps this works as you
expect today, but this technique is really unsafe and unreliable.
When the command line parser takes apart your string, it will trim
trailing blanks from the parameter values being parsed. If you can
guarantee that your data structure will never have trailing blanks, then
you're safe enough to do it this way. Otherwise, the command parser will
reserve enough storage to contain the trimmed data. If this length is
not the same as the parm length defined in your program, then you could
get garbage at the end of your DS...
Chuck's HEX trick is really clever...
Koester, Michael on Thursday, May 24, 2012 4:41 PM
Okay, Tommy Holden gets all the extra points!
My test program that submits the longer-running job just
successfully passed the data-structure as a parm, intact, and
without having to "hexify" anything. Debugging the submitted job
showed all the subfields have the intended values, and all is cool.
// Where NMS_OrderDetails is the name of the data structure
// from the copybook and PROVSN_NMS is the program that will
// run from a different job queue because it takes awhile...
Command = 'SBMJOB CMD(CALL PGM(PROVSN_NMS) PARM('''
+ NMS_OrderDetails
+ ''')) JOB(TESTING) jobq(QBATCH4)';
CallP QCMDEXC(%trim(COMMAND) : %len(%trim(COMMAND)));
Who would have thought it would be that easy. (Not me, obviously)
Thanks to all for the elegant (if perhaps more complicated than
necessary) ideas.
As an Amazon Associate we earn from qualifying purchases.