Page 1 of 2

How to call batch loader from a program?

PostPosted: Thu Sep 04, 2014 6:24 pm
by AntonioS
When trying to use the batch loader from within a program as described in IBM's MVS Program Management: User's Guide and Reference (http://pic.dhe.ibm.com/infocenter/zos/v2r1/index.jsp?topic=%2Fcom.ibm.zos.v2r1.ieab100%2Fiea3b1_Invoking_the_batch_loader_from_a_program.htm), I am not very successful, obviously because I do not understand how to pass the parameters.

In the above guide, they say

The sequence of the 8-byte entries in the ddname list for the batch loader is as follows


but I do not understand what 8-byte entries of which ddname list they are talking about, as I cannot find a description of the parms that have to be passed when calling HEWLD. The call fails with a S0C4 within HEWLD, probably because it tries to use parms I did not pass.

Can anyone give me a hint about where to find details on the parm list?

Re: How to call batch loader from a program?

PostPosted: Thu Sep 04, 2014 8:50 pm
by steve-myers
         LINK  EP=...,PARAM=(PARM1,PARM2),VL=1
         ...
PARM1    DC    H'length',C'text parameter'
PARM2    DC    H'length'
         DC    CL8'ddname'  or  XL8'0'
         DC    CL8'ddname'  or  XL8'0'

I don't recall the program names off the top of my head, but something like what I show, or its equivalent, will work. The first parameter is the usual text parameters like you would use on an JCL EXEC statement. The second parameter is alternate DD names. The length is the number of bytes in the list. The list is positional; you code the 8 byte alternate DD name, or XL8'0' to use the standard DD name for that position. I have working code somewhere, but I'd have to dig it up. After you've done this with a few different programs you'll find there is a sort of order in this madness. For example, the alternate name for SYSIN is almost always at the same position in the list. If you cut off the list with fewer entries than the maximum size if the list, the program will use the standard DD name for any missing entries.

The VL=1 in the LINK macro is required so the program knows the last pointer in the parameter list.

Re: How to call batch loader from a program?

PostPosted: Thu Sep 04, 2014 11:19 pm
by steve-myers
Here is a very simple, but complete, working example
DDLIST   CSECT                     Define program CSECT
         USING *,12                Estanlish program addressability
         SAVE  (14,12),,*          Save registers
         LR    12,15               Prepare program base register
         LA    15,SAVEAREA         Compute new save area address
         ST    13,4(,15)           Add new save area to the
         ST    15,8(,13)            save area chain
         LR    13,15               Establish new save area pointer
         L     2,0(,1)             Load address of the parm text
         N     2,=A(X'7FFFFFFF')   Turn the VL bit off
         LINK  EP=IEBGENER,PARAM=((2)),  Run IEBGENER with an          X
               MF=(E,PARMLIST)            alternate parameter list
         L     13,4(,13)           Load address of the high save area
         RETURN (14,12),T,RC=(15)  Restore registers and return
SAVEAREA DC    9D'0'               72 byte register save area
         LTORG ,                   Insert the literal pool here
PARMLIST CALL  ,(*-*,PARM2),VL,MF=L  Parameter list
PARM2    DC    AL2(LENGTH)
         DC    4XL8'00'            4 place holders
         DC    CL8'IEBIN'          SYSIN
         DC    CL8'IEBPRINT'       SYSPRINT
         DC    XL8'0'              Place holder
         DC    CL8'IEBUT1'         SYSUT1
         DC    CL8'IEBUT2'         SYSUT2
LENGTH   EQU   (*-PARM2)-2         Define DD list length
         END   DDLIST

One difference between my simplified skeleton and this example is it uses a remote parameter list defined by the list form of a CALL macro. The VL bit is important; many programs that tolerate a DD list also accept additional parameters, and they will get confused if the VL bit is not in the appropriate place. Another thing is many programmers place the length of the DD list in the 7th and 8 bytes of a double word so that each DD name is in a double word aligned 8 byte area. In fact the DFSMS Utilities manual, which I consulted when preparing my little program, seems to imply this is required. This, of course, is not true. As it happens, in my little program, the length field turned out to be in the 5th and 6th byte of a double word, and each DD name spanned a double word.

I will leave it to the numerous lurkers to figure out why the EQU statement that defines the LENGTH symbol was coded the way it was coded.

Re: How to call batch loader from a program?

PostPosted: Fri Sep 05, 2014 7:43 am
by steve-myers
AntonioS wrote:... but I do not understand what 8-byte entries of which ddname list they are talking about, as I cannot find a description of the parms that have to be passed when calling HEWLD. The call fails with a S0C4 within HEWLD, probably because it tries to use parms I did not pass.

Can anyone give me a hint about where to find details on the parm list?

Look here. You really should be using the Binder programs, not the old OS/360 based programs.

Look at this -
DDLISTL  CSECT                     Define program CSECT
         USING *,12                Estanlish program addressability
         SAVE  (14,12),,*          Save registers
         LR    12,15               Prepare program base register
         LA    15,SAVEAREA         Compute new save area address
         ST    13,4(,15)           Add new save area to the
         ST    15,8(,13)            save area chain
         LR    13,15               Establish new save area pointer
         L     2,0(,1)             Load address of the parm text
         N     2,=A(X'7FFFFFFF')   Turn the VL bit off
         LOAD  EPLOC=LOADER        Load HEWLD
         LR    15,0                Copy its address to reg 15
         CALL  (15),((2)),MF=(E,PARMLIST)  Run it
         LR    11,15               Copy the return code to reg 11
         CHI   15,4                Test return code
         BH    RETURN              Br if load failed
         L     0,4(,1)             Load length of loaded program
         L     1,0(,1)             Load address of loaded program
         FREEMAIN R,LV=(0),A=(1)   Free its storage
         DELETE EPLOC=LOADER       Delete the batch loader
RETURN   L     13,4(,13)           Load address of the high save area
         LR    15,11               Copy the loader's return code to    X
                                    reg 15
         RETURN (14,12),T,RC=(15)  Restore registers and return
SAVEAREA DC    9D'0'               72 byte register save area
LOADER   DC    CL8'HEWLD'          Name of the batch loader
         LTORG ,                   Insert the literal pool here
PARMLIST CALL  ,(*-*,PARM2),VL,MF=L  Parameter list
PARM2    DC    AL2(LENGTH)
         DC    CL8'OBJECT'         SYSLIN
         DC    2XL8'00'            2 place holders
         DC    CL8'LDRLIB'         SYSLIB
         DC    XL8'0'              Place holder
         DC    CL8'LDRPRINT'       SYSLOUT
LENGTH   EQU   (*-PARM2)-2         Define DD list length
         END   DDLISTL

The MVS Program Management: User's Guide and Reference appears to claim you can run HEWLD using the LINK macro, but I got an S406 when I tried it. I had to look up the ABEND; HEWLD is linked as "only loadable," which means the only way to load it into storage is by using the LOAD macro. After thinking about it I realized it made sense; you do not want to run HEWLD from JCL; it just loads a program but does not run it.

Re: How to call batch loader from a program?

PostPosted: Mon Sep 08, 2014 11:03 pm
by AntonioS
steve-myers wrote:
AntonioS wrote:... but I do not understand what 8-byte entries of which ddname list they are talking about, as I cannot find a description of the parms that have to be passed when calling HEWLD. The call fails with a S0C4 within HEWLD, probably because it tries to use parms I did not pass.

Can anyone give me a hint about where to find details on the parm list?

Look here.


That is exactly where I looked, but it does not explain how this dd name list has to be passed. It seems to refer to somewhere else where this is generally explained, but I was unable to find the right reference.

However, thank you very much for the examples! I will go ahead and try to make my code work based on them.

steve-myers wrote:You really should be using the Binder programs, not the old OS/360 based programs.


Not sure if I understand what you mean by the Binder programs. I had checked the IEWBIND description, but it appeared to me as it could not do the same for me as HEWLD - i.e. to load a given load module into virtual storage without identifying it. Am I wrong?

Re: How to call batch loader from a program?

PostPosted: Tue Sep 09, 2014 5:48 am
by steve-myers
AntonioS wrote:
steve-myers wrote:You really should be using the Binder programs, not the old OS/360 based programs.


Not sure if I understand what you mean by the Binder programs. I had checked the IEWBIND description, but it appeared to me as it could not do the same for me as HEWLD - i.e. to load a given load module into virtual storage without identifying it. Am I wrong?
The Binder appeared in the 1990s as a greatly improved - especially in performance - Linkage Editor.

The "batch loader" - a linking loader - originally appeared in the late 1960s. In this context, a "linking loader" is a program that combines the basic linkage editor functions and prepares an executable program in storage.

JCL like this appeared in several places and was frequently executed.

//LKED EXEC PGM=IEWL,...
//SYSPRINT DD SYSOUT=*
//SYSUT1 DD ...
//SYSLIB DD ...
//SYSLMOD DD DISP=(NEW,PASS),..,DSN=&&GOSET(GO)
//SYSLIN DD ...
//GO EXEC PGM=*.LKED.SYSLMOD

The statements in red were particularly wasteful, especially since OS/360 JCL processing was very slow. The temporary data set allocated by the SYSLMOD DD statement was especially wasteful since it was usually used once and subsequently discarded.

All this JCL was in cataloged procedures, and there were frequently problems overriding the SYSLMOD DD statement. This caused many reruns, and sometimes programmers managed to delete their load library data set!

The batch loader replaced the preceding JCL with

//GO EXEC PGM=LOADER,...
//SYSLOUT DD SYSOUT=*
//SYSLIB DD ...
//SYSLIN DD ...

In other words, it replaced two job steps with one job step, and did not allocate the SYSUT1 temporary data set or the SYSLMOD data set.

Unfortunately, the batch loader did not work out well, for at least three reasons
  • Then, as now, programmers were reluctant to change JCL, which they often did not understand very well, with new JCL to use the batch loader.
  • Combining execution JCL with the JCL to run the batch loader was confusing for many programmers.
  • Analysis of program ABENDs, especially in the MVT environment was different. The dumps were different, and were all too often useless.
The Binder appeared in the 1990s as a replacement for the Linkage Editor. The 1960s "batch loader" program disappeared as a completely separate program and product; it was now part of the Binder. The SYSLIN data set could have Binder control statements in addition to the "object module" data accepted by the "batch loader," which caused other issues with the intended users of the "batch loader."

Well, enough history lesson, which you're probably not interested in anyway.

Another question you seemed to have concerned DD lists. I went back to the manual, and I think I understand why you're confused. I think, between my previous discussion and the contents of the manual, that you should understand them well enough for your purposes.

Now, why use the linking loader function of the Binder in place of the "batch loader?" The old "batch loader" cannot analyze program objects prepared by the Binder.

Finally, you have not told us what you intend to do with the loaded program prepared by the linking loader.

If you intend to execute the program, you should use the load with "identify" function of the linking loader, and use the LINK or ATTACH macros to run the loaded program by name rather than use the CALL macro. LINK or ATTACH will handle address mode switching which a simple CALL macro will not.

Now, you ask, what's the "identify" stuff? A very good question, if you have gotten this far. IDENTIFY is a macro a programmer can use to add a module name to the job pack area. The linking loader uses an undocumented feature of the IDENTIFY macro to add the entire loaded module to the job pack area. If you are not going to execute the loaded module there is no good reason to bother, but if you are going to execute the program, then use it.

Re: How to call batch loader from a program?

PostPosted: Thu Sep 11, 2014 12:19 am
by AntonioS
Your history lesson is very interesting in fact! Thank you very much for your in-depth explanation. It is often very useful to know these details in order to understand why some things are how they are.

Now let me tell you what I am trying to do. My plan was to use the batch loader to load a load module, but not identify it, because I want to be able to do some preprocessing before this load module gets control, and after that, pass control to the load module (by a simple CALL oder even BASSM for an AMODE change). The idea was to write a program that uses the batch loader to perform the loading only. As far I understood the description of the IEWBIND macros in z/OS MVS Program Management: Advanced Facilities, the binder could do the same for me if I use the FUNC=LOADW park of the macro.

Is this correct?

Re: How to call batch loader from a program?

PostPosted: Thu Sep 11, 2014 4:47 am
by steve-myers
BASSM will certainly reset the AMODE, but the return to your program will not reset it. It also effectively forces your program to be RMODE 24, AMODE 24, which you may not want.

I think you're right to avoid the Binder macros; to me they are very confusing, and I've been trying to make sense of them for the better part of 20 years to replace direct analysis of load module CESD and IDR data. They are really intended for programs like AMASPZAP or AMBLIST. The Binder was originally developed by the Data Facility Product people; these people are fanatical about not revealing details like the internal formats of program objects, even within IBM. Until the late 1990s, it was difficult to find the internals of load modules, though I think CICS was doing doing direct loads of load modules to do the I/O within their I/O environment from the beginning. I think their stated reasons are completely stupid, even though there seems to be official support for this within IBM.

Re: How to call batch loader from a program?

PostPosted: Fri Oct 03, 2014 6:47 pm
by AntonioS
Please let me get back to this discussion because I am still confused and hope you can clarify things for me…

I have been experimenting with the HEWLD sample code you thankfully posted, but I still seem to be unable to understand how the batch loader! Shame on me!

My problem is that I cannot find information on how to tell the batch loader what I want. My assumptions are: the object library in SYSLIN is not required because according to the user's guide and reference, I understand that the loader does not handle objects but load modules (which is just what I would expect). But then, would it expect them to be in SYSLIB? Next, I do not understand how to pass the load module name to HEWLD. I tried to use INCLUDE for that, but it wasn't accepted by the loader.

Sorry for those stupid questions, but I searched the IBM documentation and I have been finding only fragments of the information I am looking for spread among several guides which is quite confusing.

Re: How to call batch loader from a program?

PostPosted: Fri Oct 03, 2014 8:56 pm
by steve-myers
AntonioS wrote:... My problem is that I cannot find information on how to tell the batch loader what I want. My assumptions are: the object library in SYSLIN is not required because according to the user's guide and reference, I understand that the loader does not handle objects but load modules (which is just what I would expect). But then, would it expect them to be in SYSLIB? Next, I do not understand how to pass the load module name to HEWLD. I tried to use INCLUDE for that, but it wasn't accepted by the loader. ...


Using a linking loader to "load" a load module is - in my opinion - kind of dumb, though sometimes the module map might be useful. The LOAD macro is faster and easier to use.

If you insist on using the old (OS/360) batch loader, you can specify a load module in the SYSLIN data set. If you want to use an INCLUDE statement, you must use the Binder's linking loader. As you theorized, both linking loaders can process load modules in the SYSLIB data set. The OS/360 linking loader could mix load modules and object modules in the SYSLIN data set -

//SYSLIN DD -- An object module data set or member --
// DD -- A load module expressed as DSN=dataset(member) --
// DD -- An object module data set or member --
// DD -- A load module expressed as DSN=dataset(member) --
// DD -- A load module expressed as DSN=dataset(member) --

I never tried it, but this should work -
//A       EXEC PGM=IEBGENER
//SYSPRINT DD  SYSOUT=*
//SYSUT1   DD  -- DSN=load-module-ds(member) --
//SYSUT2   DD  DISP=(,PASS),UNIT=SYSDA,SPACE=(...)
//SYSIN    DD  DUMMY
//B       EXEC PGM=LOADER,PARM=MAP
//SYSLOUT  DD  SYSOUT=*
//SYSLIN   DD  DISP=OLD,DSN=*.A.SYSUT2