Showing posts with label LE. Show all posts
Showing posts with label LE. Show all posts

17 April 2014

I am HOBSET because the binder put me in APCL in CICS

(SWIDT?)

So, after a break of a few years, I am plunging back into the world of CICS.

I needed to do some testing with writing out of messages via CEEMOUT, a Language Environment call that is the issuer of messages, and used by languages–er, "members"–for diagnostics and basic output. For COBOL, DISPLAY goes here; for PL/I, PUT without FILE; for C/C++, stdout/err. In batch, this is controlled by MSGFILE. Under CICS, CEEMOUT output goes to a temporary data queue, by default CESE; this by default is defined as an external queue, and it is defined to DDNAME CEEOUT.

I started writing a driver program to put a new subroutine through its paces. However, when I tried to run it, I got an APCL abend.  This is documented in typical IBM-speak something like "LE recognized that this was an LE program, but it couldn't initialize it." Googling didn't help; the only references are to the aforementioned messages & codes manuals, and one very old reference to a PL/I for MVS and VM manual.

Since I was using some old JCL of mine from prior places, I went to some that is used in another product build. That worked, so it was time to find the differences. I started with the binding process, and it did not take long. The culprit was HOBSET=YES. This parm sets the AMODE bits on in V-cons, so it can be used in BSM and BASSM instructions if you are flipping AMODEs.  I removed it, and voilĂ , the problem went away. 

I am debating whether or not to open a PMR. The restriction is not documented in either CICS or LE documentation. I'm OK with it being a restriction, but the lack of documentation bothers me.

05 September 2012

An interesting way to implement a multi-entry-point API for an LE assembler module

Today I came up with an idea for implementing an API assembler module when LE is involved. Let me first say that although  LE is very functional and usually makes life easier for high-level languages, when assembler gets involved it complicates things until you get used to LE thinking.


The original code had an entry point which did the STM for the save area and then loaded a function code into a register. Unfortunately, this does not work well with LE because the CEEENTRY macro has the STM in it. So I came up with this interesting implementation to get the function code and have only one CEEENTRY macro. Here is a very simple example, without the required CEEPPA, CEEDSA, CEECAA, and CEETERM macros:



API      CSECT
         ENTRY INIT,READ,WRITE,TERM
INIT     DC    0H
         J     LEENTRY
READ     DC    0H
         J     LEENTRY
WRITE    DC    0H
         J     LEENTRY
TERM     DC    0H
         J     LEENTRY
LEENTRY  DC    0H 
API      CEEENTRY MAIN=NO,BASE=R11 (default base)
         L     R15,4(,R13)        Backchain save area
         L     R15,16(,R15)       Get R15 at call
* R15 now is the address of the entry point
         LA    R14,0(,R11)        Clear out HOB just in case (SEE BELOW)
         LA    R15,4(,R15)        Clear out HOB and make 1-based 
         SR    R14,R15            Calculate offset from beginning of CSECT 
         SRA   R14,2              Divide by 4, preserving sign (allows use of JM BAD)
* R14 now has a function code ranging from 1 to 4
* Obviously we add some additional checking of R14 to make sure
* it is valid for our purposes.

So now GPR14 has a value ranging from 1 to 4, with 1 being INIT, 2 being READ, etc.. Good programmers will test GPR14 for falling within the required boundaries. You could also forgo the SRA and use the value of 4, 8, 12, or 16. In current releases of z/OS, CEEENTRY uses LARL to load the base register with the address of API, so the LA of GPR14 from GPR11 could just be an LR. This also works with non-LE assembler code; if you have a base register use LA, and if "baseless" use an LARL of the CSECT name. Just make sure that if you have a standard entry macro (most shops do) that generates a CSECT, the CSECT name used at the beginning of the module has to match that generated by your macro.