MainframeSupports
tip week 24/2012:

Almost three years ago in week 28/2009 I wrote a tip about how to find a DD name by using the TIOT area. In a TIOT entry you will beside the DD name also find a pointer to the JFCB. The JFCB describes the dataset connected to the DD name. The first 44 bytes of the JFCB contains the dataset name. Unfortunately the pointer is represented as a so-called swa token three bytes long (in the former tip I call it the jfcbtoken).

The first version of the MVS operating system only used 24 bits for addressing and thus an address only needed three bytes. For reasons I am not familiar with IBM chose not to extent the JFCB address in the TIOT to four bytes when 31 bits addressing was introduced in MVS/XA. For many years it was possible to move the three bytes in the jfcbtoken to the last three bytes of a pointer and set the first byte of the pointer to low values. This approach suddenly ceased to work, because IBM moved the JFCB area above the 16 megabyte line. Instead the three bytes in the jfcbtoken was converted into a swa token. This token could be translated into a real 31 bit address by using an assembler macro.

On almost all mainframe installations around the world small assembler programs was developed to convert the swa token into an address. Unfortunately here in 2012 very few installations has documented their swa token conversion programs and fewer knows where to find the documentation. As a consequence a few people has found out how to code the swa token conversion directly in COBOL and PLI. Here is a link to a COBOL program that among other things converts a swa token. I also found a piece of PLI code doing the same thing, but unfortunately it did not work so I translated a bit of the COBOL code from the above link into a PLI procedure:

swa2addr: PROC(swa) RETURNS(POINTER);

DCL   swa CHAR(3);
DCL   svas CHAR(4);
DCL   svap POINTER BASED(addr(svas));
DCL   svab FIXED BIN(31) BASED(addr(svas));
DCL   myQmatP POINTER;
DCL   myQmatB FIXED BIN(31) BASED(addr(myQmatP));
DCL   jfcbPointer POINTER BASED(svaP);
DCL   psaPointer POINTER STATIC INIT(sysNull());
DCL 1 psa BASED(psaPointer)
  , 2 * CHAR(536)
  , 2 tcbPointer POINTER
  ;
DCL 1 tcb BASED(tcbPointer) UNALIGNED
  , 2 * CHAR(180)
  , 2 jscbPointer POINTER
  , 2 * CHAR(116)
  , 2 ownerPointer POINTER
  ;
DCL 1 jscb BASED(jscbPointer) UNALIGNED
  , 2 * CHAR(244)
  , 2 qmplPointer POINTER
  ;
DCL 1 qmpl BASED(qmplPointer) UNALIGNED
  , 2 * CHAR(24)
  , 2 qmatPointer POINTER
  ;
DCL 1 qmat BASED(myQmatP) UNALIGNED
  , 2 * CHAR(12)
  , 2 nextQmatP POINTER
  ;
svaS = '00'X !! swa;
IF mod(svaB, 16) = 15
THEN DO;
  myQmatP = qmatPointer;
  DO WHILE(svab > 65536);
    myQmatP = nextQmatP;
    svab = svab - 65536;
  END;
  svaB = svaB + 1 + myQmatB;
  svaP = jfcbPointer;
END;
svaB = svaB + 16;
RETURN(svaP);

END swa2addr;

If your PLI program has access to a jfcbtoken and wants to use the associated dataset name, then you can declare a CHAR(44) BASED(jfcbPointer) variable and code the assigment jfcbPointer = swa2addr(jfcbToken). This makes the dataset name accessible in your dataset name variable. Please note that some DD names do not have valid dataset names connected. Either you try out yourself which dataset names are used for diffent types of datasets or you locate a description of the JFCB and decode its contents to sort things out.

Previous tip in english        Forrige danske tip        Tip list