Joined: 28 Mar 2023 Posts: 9 Location: United Kingdom
Hi!
I'm trying to invoke IDCAMS from an assembly program, but I'm running into an issue in terms of trying to pass the DD statements that I have defined in my JCL to IDCAMS for it to use. In particular, I get a UABORT CODE 36 which I saw from the documentation means that the processor can't open SYSPRINT.
When I define AMSDUMP in RUNSTEP, I get a snap dump in the spool as expected, so it might be a problem with SYSPRINT specifically - but if so then I can't figure out what it is.
Is there any way to pass my DD statements to all invoked programs? Or maybe there is a parameter that I need to use to specify where to find the defined DD statements?
Here is the relevant snippet from the spool:
Code:
IEF236I ALLOC. FOR IDCAMJB RUNSTEP
IGD103I SMS ALLOCATED TO DDNAME STEPLIB
IEF237I JES2 ALLOCATED TO SYSPRINT
IEF237I JES2 ALLOCATED TO AMSDUMP
IGD103I SMS ALLOCATED TO DDNAME INPUTDS
IEF237I JES2 ALLOCATED TO SYSIN
IDC4999I UABORT CODE 36
IEF142I IDCAMJB RUNSTEP - STEP WAS EXECUTED - COND CODE 3952
IGD104I ALEXGAS.MYLIBS.NOAPFLIB RETAINED, DDNAME=STEPLIB
IEF285I ALEXGAS.IDCAMJB.JOB01094.D0000105.? SYSOUT
IEF285I ALEXGAS.IDCAMJB.JOB01094.D0000106.? SYSOUT
IGD104I ALEXGAS.TEMP.PDS RETAINED, DDNAME=INPUTDS
IEF285I ALEXGAS.IDCAMJB.JOB01094.D0000102.? SYSIN
IDCAMEZ CSECT # Mark as executable.
STM 14,12,12(13) # Store stack contents.
BALR 12,0 # Establish addressability by
USING *,12 # storing base addr in base reg.
ST 13,SAVE+4 # save the CALLER save area
LA 13,SAVE # load pointer to THIS save area
*
* CALL IDCAMS
*
LOAD EP=IDCAMS # Load IDCAMS into R0
LR 15,0 # Copy R0 to R15
CALL (15),(OPTIONS)
B CLEANUP # run cleanup code and return
*
* COMMON CLEANUP CODE
*
CLEANUP L 13,SAVE+4 # restore CALLER save area
LM 14,12,12(13) # restore register contents
BR 14 # branch back to caller
*
* declarations
*
SAVE DS 18F # define save area storage
OPTIONS DC X'0000' # no params so fill with 0
IDCAMEZ AMODE 31
END
is a random number (or the value restored from entry point) which has been returned in R15 from your own test. You need at least pass the R15 returned from your CALL into R15 in your own RETURN/CLEANUP, to find out the utility RC.
It is the minimum.
Another thing to do: find out what is IDC4999I UABORT CODE 36 message?
The very first attempt to use Google returned immediately:
Quote:
36
The processor was unable to open SYSPRINT (or whichever DD name is employed to denote the processor’s standard listing output data set).
This is the starting point to think about.
Verify that your PARM is constructed as IDCAMS is expecting. Looks like it is trying to substitute different DDNAME instead of SYSPRINT; there is a way to pass replacing ddnames via parameters; I'm lazy to read all this stuff instead of yourself.
For instance, there is no VL indicator, that's why IDCAMS assumed you are passing more than one parameter!!!
All these are very trivial things any developer must know from his birth day!!
Joined: 28 Mar 2023 Posts: 9 Location: United Kingdom
Hi Sergey.
Thanks for your reply, the issue was me missing out the VL indicator -- very silly mistake on my part! I suspect it was to do with it trying to read an alternative DD name that didn't exist and hence not being able to find SYSPRINT under an alternative name that didn't exist or something like that.
Now it works just fine .
Just in my defence as a new poster:
Quote:
Another thing to do: find out what is IDC4999I UABORT CODE 36 message?
I'd found out what the message meant which is why in the subject of the thread I mentioned that I wanted to pass SYSPRINT to IDCAMS and in my post I stated that:
Quote:
I get a UABORT CODE 36 which I saw from the documentation means that the processor can't open SYSPRINT.
But I digress.
Quote:
Verify that your PARM is constructed as IDCAMS is expecting. Looks like it is trying to substitute different DDNAME instead of SYSPRINT; there is a way to pass replacing ddnames via parameters; I'm lazy to read all this stuff instead of yourself.
The only required parameter is the OPTIONS LIST, but I'm not using it which is why I set the argument to 0 as per the documentation. To start with I wanted to minimise the complexity of the program and then once I got the basic version working I would try different parameters as needed.
But I'll do better next time I post on here -- I can't complain if you solved my issue after all haha.
Joined: 28 Mar 2023 Posts: 9 Location: United Kingdom
Clarification, this was my final working code -- I also added a DCB statement for it to work:
Code:
IDCAMEZ CSECT # Mark as executable.
STM 14,12,12(13) # Store stack contents.
BALR 12,0 # Establish addressability by
USING *,12 # storing base addr in base reg.
ST 13,SAVE+4 # save the CALLER save area
LA 13,SAVE # load pointer to THIS save area
*
* CALL IDCAMS
*
LOAD EP=IDCAMS # Load IDCAMS into R0
LR 15,0 # Copy R0 to R15
CALL (15),(OPTIONS),VL
B CLEANUP # run cleanup code and return
*
* COMMON CLEANUP CODE
*
CLEANUP L 13,SAVE+4 # restore CALLER save area
LM 14,12,12(13) # restore register contents
BR 14 # branch back to caller
*
* declarations
*
SAVE DS 18F # define save area storage
OPTIONS DC X'0000' # no params so fill with 0
IDCAMEZ AMODE 31
SYSPRINT DCB DSORG=PS,MACRF=PM,DDNAME=SYSPRINT, X
RECFM=FA,LRECL=133,BLKSIZE=133
END
Joined: 28 Mar 2023 Posts: 9 Location: United Kingdom
dneufarth wrote:
Why not use SAVE/RETURN macros?
Before using those macros I wanted to try and get to grips with what's happening under the hood with respect to the save area. But practically speaking it's definitely safer to use those I imagine -- they're there for a reason after all!