$ZOOM – Mother of all EDIT macro’s

The most useful ISPF EDIT macro ever. I think it was written by Paul van Goethem from Belgium, somewhere before 1993. It has quickly spread through many sites.

Point your cursor at at dataset name in a file your are editing en executing the macro will launch an EDIT session of that file.
I always put in under PF key PF4 which by default has the not very useful default value RETURN.

Note the value of the variable INVALID in the below may be corrupted. It should contain any character that is not valid as part of a dataset. The binary values it can contain are not very portable.

/****************************REXX***********************************/
/* FUNCTION: RECURSIVE EDIT OF BROWSE VIA DSNAAM AND,OR MEMBER     */
/*  SPECIFIED VIA CURSOR SENSITIVE EDIT MACRO                      */
/* FORMATS ACCEPTED:                                               */
/*  DATA.SET.NAME   : EDIT/BROWSE OF THIS                          */
/*  DATA.SET.NAME(MEMBER) : EDIT/BROWSE THIS                       */
/*  MEMBER    : EDIT/BROWSE IN SAME LIBRARY AS INDEX               */
/****************************REXX***********************************/  
ADDRESS ISPEXEC    INVALID= ",'\<\>,:;+��▖!�%�-="
ADDRESS ISREDIT 'MACRO (FUNCTIE)'
FUNCTIE = TRANSLATE(FUNCTIE)  
IF SUBSTR(FUNCTIE,1,1)='B'
THEN FUNCTIE='BROWSE'
ELSE FUNCTIE='EDIT' 
LIN=0 
ADDRESS ISREDIT '(LIN,COL) = CURSOR'  
ADDRESS ISREDIT '(CLINE) = LINE 'LIN   
/* FIND CURRENT WORD */ 
T=SUBSTR(CLINE,1,COL)  
T =TRANSLATE(T,' ',INVALID)    
Y=LASTPOS(' ',T) 
IF Y=0
THEN T=CLINE    
ELSE T=SUBSTR(CLINE,Y+1)
PARSE VAR T WOORD  .   
WOORD =TRANSLATE(WOORD,' ',INVALID)
"CONTROL ERRORS RETURN"
IF INDEX(WOORD,'(') /= 0 THEN DO /* TAKE DSN IF SPECIFIED */
  PARSE VAR WOORD  DSNAME '('  MEMBER ')' 
  FUNCTIE" DATASET('"SPACE(DSNAME)"("MEMBER")')" 
  FRC=RC
  END
ELSE DO
  IF INDEX(WOORD,'.')/=0 THEN DO   
    PARSE VAR WOORD  DSNAME . 
    FUNCTIE" DATASET('"SPACE(DSNAME)"')" 
    END  
  ELSE DO         
    ADDRESS ISREDIT "(DSNAME) = DATASET"  
    WOORD = SPACE(TRANSLATE(WOORD,' ','.()'))
    FUNCTIE" DATASET('"DSNAME"("WOORD")')"  
    END    
  FRC=RC   
  END  
ADDRESS ISPEXEC "CONTROL ERRORS CANCEL"  
IF FRC> 4 & SYMBOL(ZERRMSG)/= 'LIT' THEN DO      
  MSG= ZERRMSG':'ZERRLM            
  "SETMSG MSG(ZOM000A)"            
  END                           
RETURN

Db2 SQL in batch

Again a simple solution for a common problem: how to run a Db2 query from a batch script. Here we use the utility DSNTEP2 that is provided for this purpose with the Db2 installation.

In the STEPLIB, specify your names for Db2 runtime libraries.

In the SYSTEM (xxxx) clause specify your Db2 subsystem.

The SQL in the SYSIN label can be taken from in-stream, or from a dataset as below.

//GO EXEC PGM=IKJEFT01,DYNAMNBR=20 
//STEPLIB DD DSN=SYS2.SDSNEXIT,DISP=SHR 
//        DD DSN=SYS2.SDSNLOAD,DISP=SHR     
//SYSTSPRT DD SYSOUT=*  
//SYSTSIN DD * 
 DSN SYSTEM (xxxx)                                       
 RUN PROG (DSNTEP2)
//SYSPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//*SYSIN    DD DISP=SHR,DSN=YOURDSN.DB2.SQL(YOURSQL) OR
//SYSIN    DD *
 SELECT * FROM YOURTABLE
/*

//Dean

The new mainframe is full of APIs (and has an extension for Docker Containers)

IBM has announced the new mainframe box, not unexpectedly called z15. The z15 is a huge machine and I would summarize this evolution “bigger and better” without being disrespectful.
Nevertheless, the accompanying announcement of the new release of the flagship operating system for the z15, z/OS 2.4 is massively interesting.

The most eye-catching new feature in z/OS 2.4 is z/OS Container Extensions. With this feature you can run Linux Docker containers under z/OS, next to your existing z/OS applications. Making your Containers thus part of your z/OS infrastructure has some powerful advantages.

  • Very easy integration of containers in the Continuous Availability solution for Disaster Recovery of your z/OS platform provided by GDPS. I think this is by far the most powerful benefit. Thus you can provide Linux on z solutions even more easily than through a native Linux for z deployment.
  • Exploit the capabilities of network virtualization of z/OS.
  • Optimized integration with z/OS workloads.

The second important item to look at is the evolution of z/OSMF. Contrary to what IBM Marketing tells us I believe the second important item in my opinion is not Container Pricing, and not Open Data Analytics on z/OS. The development of z/OSMF is more important because it is fundamentally changing the consumability of the platform, turning the platform into the most open computing platform in the market, through the availability op REST APIs on basically any resource on the platform. And fundamentally transforming the way the platform is managed.

It is exciting to see how the mainframe is changing at the moment. The movements of the last five years are really turning the mainframe from a self-oriented platform into one of the most open and accessible technologies on the market.

The only thing left in my opinion is an affordable, public and easily accessible facility to the platform in order to boost the collaborative community around the platform.

The definition of a user catalog

Ok another short one: just a small JCL script with working example for the definition of a user catalog. This would accompany the example of the alias definition for a user catalog that can be found here.

//DEFCAT   EXEC PGM=IDCAMS                               
//SYSPRINT DD SYSOUT=*                                  
//SYSIN    DD *                                       
DEFINE UCAT (NAME(SYS1.USERCAT.PROD) VOLUME(DASD1B) - 
        CYL(6,1) ICFCAT  )          

Enjoy.

Pierre G.

How to copy the contents of a catalog: IDCAMS

A very short one, but regularly asked by my mentees: how to copy the contents of a catalog? Just use IDCAMS’ REPRO facility, like you would for a regular VSAM dataset

//COPYCAT   EXEC PGM=IDCAMS                           
//SYSPRINT DD SYSOUT=*                         
//SYSIN    DD *                                      
REPRO  INDATASET(CATALOG.MVSICFM.VD9ECAT) -         
        OUTDATASET(SYS1.MSTRCTLG)    

//Pierre G

Change the volume of the entry for a dataset in a catalog

When you have defined a dataset in the wrong catalog – in this case a master catalog – and you want to correct this you can use this technique.The DELETE NOSCRATCH option assures only the catalog entry is deleted. If you would omit this, the entire dataset would be deleted, so be cautious.

//DEFCAT   EXEC PGM=IDCAMS          
//STEPCAT DD DISP=SHR,DSN=SYS1.MSTRCTLG           
//SYSPRINT DD SYSOUT=*                          
//SYSIN    DD *                  
DELETE (SYS1.DATASET) NVSAM NOSCRATCH CAT(SYS1.MSTRCTLG)     
DEFINE NVSAM (NAME(SYS1.DATASET) DEVT(3390) VOL(VOL123)) - 
            CAT(SYS1.MSTRCTLG)   

//Pierre G

Allocate a page dataset / page space for new system, in a second master catalog

This job shows you how you can define a page dataset in another master catalog than the currently active master catalog. This technique is typically used when you are building a new system from a driver system. The master catalog referred to via the CATALOG statement below is the to-be master catalog of the new system you are building.

//DEFPAGE EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//PAGE2    DD UNIT=3390,VOL=SER=PSYS1B,DISP=OLD
//SYSIN    DD *
  DEFINE PAGESPACE( -
      FILE(PAGE2) -
      NAME(SYS1.MVST.PLPA2) -
      CYLINDERS(300) -
      VOLUME(PSYS1B) ) -
    CATALOG(SYS1.MSTRCAT0)
/* 

//Pierre G.

Define an ALIAS for your User Catalog

This JCL defines an ALIAS in the current master catalog. The alias points to the user catalog named in the RELATE clause.

Use a STEPCAT pointing to another master catalog when needed.

//DEFCAT   EXEC PGM=IDCAMS 
//* STEPCAT DD DISP=SHR etc when needed     
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *        
  DEF ALIAS (NAME(PROD) RELATE(SYS1.USERCAT.PROD)) 
/*
//

//Pierre G

ABEND Assembler program

I can not remember why I needed this assembler program – and why it is in assembler – but here it is: the program who’s sole function is to ABEND

ABENDIT  CSECT
         EQUATES
         SAVE (14,12),,ABENDIT/SPDEPT/&SYSDATE/&SYSTIME/
         USING ABENDIT,R11             SET UP BASE ADDRESSABILITY
         LR    R11,R15                 LOAD BASE REG WITH ENTRY POINT
         LA    R14,SAVE                GET ADDRESS OF REGISTER SAVE
         ST    R13,4(0,R14)            SAVE CALLER'S SAVE AREA ADDR
         ST    R14,8(0,R13)            SAVE MY SAVE AREA ADDRESS
         LR    R13,R14                 LOAD SAVE AREA ADDRESS 
*        Business Logic
         ABEND 4321
*        Epilogue 
RETURN   EQU    *
         L      R13,4(R13) 
         RETURN (14,12)                RETURN TO CALLER 
         LTORG 
SAVE     DS     18F 
         END ABENDIT 

// Bert Grobs

Ways get utc / gmt time zone (offset) versus local time in Rexx on z/OS

Regularly we need to compare local time to absolute time UTC (or GMT) programmatically.

This can be done in various ways.

The cleanest way is to use the static system symbols that z/OS defines. See also section “Static System Symbols” in the z/OS Initialization and Tuning Reference.You can easily use this in a Rexx program. For example: 

/* Rexx */  
/* Display UTC Time elements */
say  mvsvar('SYMDEF','HR')      
say  mvsvar('SYMDEF','MIN')     
say  mvsvar('SYMDEF','SEC')     
say  mvsvar('SYMDEF','HHMMSS')  
say  mvsvar('SYMDEF','LHHMMSS') 

It is also possible through Unix System Services date command to obtain UTC:

date -u
Wed Aug 21 15:20:42 GMT 2019 

A more complex way (old fashioned) to achieve the same is addressing the CVT extension block:

                   
cvt = c2d(storage(d2x(16),4))                                
cvtext2 = c2d(storage(d2x(cvt + 328 ),4))
offset  = ((c2d(storage(d2x(cvtext2+56+2),4))) * 16) /3600000000 
timezone = "+0"||offset||"00"                   

Thanks to Henk for the latter two solution alternatives.

— Niek de Greef